栈与队列的实现

栈与队列的实现

后进先出:插入与删除操作都在栈顶

数组实现栈

核心思想
  • 使用一数组存储栈元素(例如 A ),栈顶指针 top 记录栈顶元素的索引。

  • 将 top 初始化为 -1 ,表示栈为空。

  • 通过对索引的加减等操作,实现入栈、出栈等操作

核心操作
  • push(x) : 入栈

    push(x){
        top = top + 1;   //栈顶指针+1
        A[top] = x;
    }

  • pop() : 出栈

    pop(){
        if(top == -1) {  // 栈空判断
            printf("No element to pop \n");
            return;
        }
        top = top - 1;  /*栈顶指针减 1,直接将索引向前移一位,不用清除此处的数据,因为下次给此处赋值时会覆盖掉上次的数据*/
    }

  • top() : 获取栈顶元素的值(不删除)

    Top(){
        return A[top];  //直接返回栈顶元素的值
    }

  • IsEmpty() : 判断栈是否为空

    int IsEmpty(){
        if(top == -1){
            return true;
        }else{
            return false;
        }
    }

溢出问题及解决
  • 当数组已满(top == 数组长度 - 1)时,继续入栈则会触发栈溢出

  • 解决方案:创建更大的数组,将原来数组内所有元素复制到新数组( 新数组 一般为 原数组 的两倍)

代码实现
#include<stdio.h>
#define MAX_SIZE 101  // 定义栈的最大容量
int A[MAX_SIZE];     // 用数组A存储栈元素
int top = -1;        // 栈顶指针,初始为-1表示栈空
​
// 入栈操作:将元素x压入栈顶
void Push(int x) {
    if(top == MAX_SIZE - 1) {  // 栈满判断
        printf(" stack overflow \n");
        return;
    }
    A[++top] = x;  // 栈顶指针先加1,再存入元素
}
​
// 出栈操作:从栈顶弹出一个元素
void Pop() {
    if(top == -1) {  // 栈空判断
        printf("No element to pop \n");
        return;
    }
    top--;  //栈顶指针减1
}
​
// 获取栈顶元素
int Top() {
    if(top == -1) {
        printf("栈为空\n");
        return -1;
    }
    return A[top];
}
​
// 使用示例(可根据需求调用上述操作)
int main() {
    Push(10);
    Push(20);
    printf("栈顶元素:%d\n", Top());
    Pop();
    printf("出栈后栈顶元素:%d\n", Top());
    return 0;
}

上述实现简单直观,但也存在一些 缺点:

  • 不能在一个程序中创建多个栈

  • 大小固定,无法动态调整

因此更好的方法是通过 结构体 来实现:

  • 可将栈的状态封装在结构体中

    • 为什么要封装:

      • 将相关的数据组织在一起

      • 隐藏内部实现细节

      • 提供统一的接口操作

  • 可创建多个独立的栈

  • 可根据需要自动调整大小

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    ​
    #define INIT_CAPACITY 10
    ​
    typedef struct {
        int *data;      //动态数组指针
        int top;        //栈顶指针
        int capacity;   //当前容量
    }ArrayStack;
    ​
    //创建栈:在堆上分配内存
    ArrayStack* creat_ArrayStack() {
        ArrayStack* stack = (ArrayStack*)malloc(sizeof(Arraystack));   //分配栈结构体本身的内存
        stack->data = (int*)malloc(sizeof(int) * INIT_CAPACITY);      //分配数据数组的内存
        //初始化其他
        stack->top = -1;
        stack->capacity = INIT_CAPACITY;
        return stack;
    }
    ​
    //判断栈是否为空
    bool IsEmpty(Arraystack* stack) {
        return stack->top == -1;
    }
    ​
    //判断栈是否已满
    bool IsFull(ArrayStack* stack) {
        return stack->top == stack->capacity - 1;
    }
    ​
    //扩容
    void resize_ArrayStack(ArrayStack* stack) {
        int newCapacity = stack->capacity * 2;
        int* newData = (int*)malloc(sizeof(int) * newCapacity);
        
        for(int i = 0; i <= stack->top; i++) {    //将原数组复制到新数组
            newData[i] = stack->data[i];
        }
        
        free(stack->data);
        stack->data = newData;
        stack->capacity = newCapacity;
        printf("已扩容,新容量:%d\n", newCacity);
    }
    ​
    //入栈
    void push(ArrayStack* stack, int val) {
        if (IsFull(stack)) {
            resize_ArrayStack(stack);
        }
        stack->data[++stack->top] = val;
    }
    ​
    //出栈
    int pop(ArrayStack* stack) {
        if (IsEmpty(stack)) {
            printf("栈为空,无法出栈\n");
            return -1;
        }
        return stack->data[stack->top--];   //返回被弹出的数,并将栈顶指针减 1
    }
    ​
    //查看栈顶元素
    int Top(ArrayStack* stack){
        if (IsEmpty(stack)) {
            printf("栈为空\n");
            return -1;
        }
        return stack->data[stack->top];
    }
    ​
    //获取栈大小
    int Size(ArrayStack *stack) {
        return stack->top + 1;
    }
    ​
    //打印栈
    void print_ArrayStack(ArrayStack *stack) {
        if (IsEmpty(stack)) {
            printf("栈: []\n");
            return;
        } 
        printf("栈: [");
        for (int i = 0; i <= stack->top; i++) {
            printf("%d", stack->data[i]);
            if (i < stack->top) printf(", ");
        }
        printf("]\n");
    }
    ​
    //释放栈
    void free_ArrayStack(ArrayStack* stack) {
        free(stack->data);    //释放前边为数组分配的内存
        free(stack);         //释放前边为结构体本身分配的内存
    }

链表实现栈

核心思想
  • 链表实现栈时,以链表头部作为栈顶,所有操作都在头部进行

  • 入栈:创建新节点,指针域指向原栈顶节点,再将栈顶指针指向新节点

  • 出栈:将栈顶指针向后移一位,释放原栈顶节点

代码实现
//链表节点的定义
typedef struct ListNode {
    int val;
    struct ListNode* next;
} ListNode;
​
// 创建新节点
ListNode* createNode(int value) {
    ListNode* node = (ListNode*)malloc(sizeof(ListNode));
    node->val = value;
    node->next = NULL;
    return node;
}
​
​
//链表实现栈
typedef struct {
    ListNode* top;
    int size;
} LinkedStack;
​
// 初始化栈
LinkedStack* create_LinkedStack() {
    LinkedStack* stack = (LinkedStack*)malloc(sizeof(LinkedStack));
    stack->top = NULL;
    stack->size = 0;
    return stack;
}
​
// 判断栈是否为空
bool IsEmpty(LinkedStack* stack) {
    return stack->top == NULL;
}
​
// 入栈
void Push(LinkedStack* stack, int value) {
    ListNode* newNode = createNode(value);
    newNode->next = stack->top;
    stack->top = newNode;
    stack->size++;
}
​
// 出栈
int Pop(LinkedStack* stack) {
    if (IsEmpty(stack)) {
        printf("栈为空,无法出栈\n");
        return -1;
    }
    
    ListNode* temp = stack->top;
    int value = temp->val;
    stack->top = stack->top->next;
    free(temp);
    stack->size--;
    return value;
}
​
// 查看栈顶元素
int Top(LinkedStack* stack) {
    if (IsEmpty(stack)) {
        printf("栈为空\n");
        return -1;
    }
    return stack->top->val;
}
​
// 获取栈大小
int Size(LinkedStack* stack) {
    return stack->size;
}
​
// 打印栈
void print_LinkedStack(LinkedStack* stack) {
    if (IsEmpty(stack)) {
        printf("栈: []\n");
        return;
    }
    
    printf("栈: [");
    ListNode *current = stack->top;
    while (current != NULL) {
        printf("%d", current->val);
        if (current->next != NULL) printf(", ");
        current = current->next;
    }
    printf("]\n");
}
​
// 释放栈
void free_LinkedStack(LinkedStack* stack) {
    while (!IsEmpty(stack)) {
        Pop(stack);
    }
    free(stack);
}

队列

先进先出:队尾进入,队首离开

数组实现队列

核心思想
  • 设置两个索引分别代表队首(front)和队尾(rear),二者都为 -1 时表示队列为空

  • 队列的长度为 front 和 rear 之间的长度

  • 入队:将 rear后移一位,给该处赋值

    • 当数组最后填满而前面空间仍有剩余时,可以使用循环数组实现对该空间的利用:(queue->front + i) % queue->capacity

  • 出队:将 front 后移一位

代码实现
typedef struct {
    int* data;
    int front;
    int rear;
    int size;
    int capacity;
} ArrayQueue;
​
// 初始化队列
ArrayQueue* create_ArrayQueue() {
    ArrayQueue* queue = (ArrayQueue*)malloc(sizeof(ArrayQueue));
    queue->capacity = INIT_CAPACITY;
    queue->data = (int*)malloc(sizeof(int) * queue->capacity);
    queue->front = 0;
    queue->rear = 0;
    queue->size = 0;
    return queue;
}
​
// 判断队列是否为空
bool IsEmpty(ArrayQueue* queue) {
    return queue->size == 0;
}
​
// 判断队列是否已满
bool IsFull(ArrayQueue* queue) {
    return queue->size == queue->capacity;
}
​
// 扩容
void resize_ArrayQueue(ArrayQueue* queue) {
    int newCapacity = queue->capacity * 2;
    int* newData = (int*)malloc(sizeof(int) * newCapacity);
    
    // 将原队列元素复制到新队列
    for (int i = 0; i < queue->size; i++) {
        newData[i] = queue->data[(queue->front + i) % queue->capacity];
    }
    
    free(queue->data);
    queue->data = newData;
    queue->front = 0;
    queue->rear = queue->size;
    queue->capacity = newCapacity;
    printf("队列已扩容,新容量: %d\n", newCapacity);
}
​
// 入队
void Enqueue(ArrayQueue* queue, int value) {
    if (IsFull(queue)) {
        resizeArrayQueue(queue);
    }
    queue->data[queue->rear] = value;
    queue->rear = (queue->rear + 1) % queue->capacity;
    queue->size++;
}
​
// 出队
int Dequeue(ArrayQueue* queue) {
    if (IsEmpty(queue)) {
        printf("队列为空,无法出队\n");
        return -1;
    }
    int value = queue->data[queue->front];
    queue->front = (queue->front + 1) % queue->capacity;
    queue->size--;
    return value;
}
​
// 查看队头元素
int Front(ArrayQueue* queue) {
    if (IsEmpty(queue)) {
        printf("队列为空\n");
        return -1;
    }
    return queue->data[queue->front];
}
​
// 获取队列大小
int Size(ArrayQueue* queue) {
    return queue->size;
}
​
// 打印队列
void print_ArrayQueue(ArrayQueue* queue) {
    if (IsEmpty(queue)) {
        printf("队列: []\n");
        return;
    }
    
    printf("队列: [");
    for (int i = 0; i < queue->size; i++) {
        printf("%d", queue->data[(queue->front + i) % queue->capacity]);
        if (i < queue->size - 1) printf(", ");
    }
    printf("]\n");
}
​
// 释放队列
void free_ArrayQueue(ArrayQueue* queue) {
    free(queue->data);
    free(queue);
}

链表实现队列

核心思想
  • 使用两个指针 front 和 rear 分别指向链表的头部和尾部

  • 入队:使原尾节点指向新节点,再使 rear 指向新节点

  • 出队:将 front 后移一位,并释放原头节点

代码实现
//定义链表节点
typedef struct ListNode {
    int val;
    struct ListNode* next;
} ListNode;
​
// 创建新节点
ListNode* createNode(int value) {
    ListNode* node = (ListNode*)malloc(sizeof(ListNode));
    node->val = value;
    node->next = NULL;
    return node;
}
​
​
//链表实现队列
typedef struct {
    ListNode* front;
    ListNode* rear;
    int size;
} LinkedQueue;
​
// 初始化队列
LinkedQueue* create_LinkedQueue() {
    LinkedQueue* queue = (LinkedQueue*)malloc(sizeof(LinkedQueue));
    queue->front = NULL;
    queue->rear = NULL;
    queue->size = 0;
    return queue;
}
​
// 判断队列是否为空
bool IsEmpty(LinkedQueue* queue) {
    return queue->front == NULL;
}
​
// 入队
void Enqueue(LinkedQueue* queue, int value) {
    ListNode* newNode = createNode(value);
    
    if (IsEmpty(queue)) {
        queue->front = queue->rear = newNode;
    } else {
        queue->rear->next = newNode;
        queue->rear = newNode;
    }
    queue->size++;
}
​
// 出队
int Dequeue(LinkedQueue* queue) {
    if (IsEmpty(queue)) {
        printf("队列为空,无法出队\n");
        return -1;
    }
    
    ListNode* temp = queue->front;
    int value = temp->val;
    queue->front = queue->front->next;
    
    // 如果出队后队列为空,需要更新rear指针
    if (queue->front == NULL) {
        queue->rear = NULL;
    }
    
    free(temp);
    queue->size--;
    return value;
}
​
// 查看队头元素
int Front(LinkedQueue* queue) {
    if (IsEmpty(queue)) {
        printf("队列为空\n");
        return -1;
    }
    return queue->front->val;
}
​
// 获取队列大小
int Size(LinkedQueue* queue) {
    return queue->size;
}
​
// 打印队列
void print_LinkedQueue(LinkedQueue* queue) {
    if (IsEmpty(queue)) {
        printf("队列: []\n");
        return;
    }
    
    printf("队列: [");
    ListNode *current = queue->front;
    while (current != NULL) {
        printf("%d", current->val);
        if (current->next != NULL) printf(", ");
        current = current->next;
    }
    printf("]\n");
}
​
// 释放队列
void free_LinkedQueue(LinkedQueue* queue) {
    while (!IsEmpty(queue)) {
        Dequeue(queue);
    }
    free(queue);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值