栈和队列

Posted sanweizuiji

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈和队列相关的知识,希望对你有一定的参考价值。

1 栈

C n m = A n m m ! = n ! m ! ( n − m ) ! C_n^m =\\fracA_n^mm ! =\\fracn !m !(n-m) ! Cnm=m!Anm=m!(nm)!n!

1.1 栈的顺序存储实现

#include <stdio.h>

#define MAXSIZE 10

// 自定义顺序栈结构体
struct mySqStack 
    // 静态数组存放栈中元素
    int data[MAXSIZE];
    // 栈顶指针
    int top;
;
typedef struct mySqStack SqStack;

SqStack initStack() 
    SqStack S;
    S.top = -1;
    return S;


SqStack push(SqStack S, int x) 
    if (S.top == MAXSIZE - 1) 
        printf("栈满,入栈失败!");
     else 
        // top指针+1
        S.top++;
        S.data[S.top] = x;
    
    return S;


SqStack pop(SqStack S) 
    if (S.top == -1) 
        printf("空栈,出栈失败!");
     else 
        int x = S.data[S.top];
        S.top--;
        printf("%d 出栈", x);
    
    return S;


// 读取栈顶元素
int getTop(SqStack S) 
    if (S.top == -1) 
        printf("空栈,读取失败!");
        return -999;
    
    return S.data[S.top];


// 打印栈中的元素
void printStack(SqStack S) 
    printf("\\n");
    int js = 0;
    for (int i = S.top; i >= 0; i--) 
        printf("%d ", S.data[i]);
        js++;
    
    printf("\\n");


int main() 
    SqStack S;
    S = initStack();
    for (int i = 0; i < 11; i++) 
        S = push(S, i);
    
    S = pop(S);
    getTop(S);
    printStack(S);
    return 0;

1.2 栈的链式存储实现

#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>

// 自定义链式栈结构体
struct myChainStackNode 
    int data;
    struct myChainStackNode *next;
;
typedef struct myChainStackNode ChainStackNode;

// 初始化栈
ChainStackNode *initStack() 
    // 创建头节点
    ChainStackNode *node = (ChainStackNode *) malloc(sizeof(ChainStackNode));
    // 初始化为空
    node->next = NULL;
    return node;


// 判断栈是否为空
bool stackIsEmpty(ChainStackNode *node) 
    if (node->next == NULL) 
        return true;
     else 
        return false;
    


// 新元素入栈
ChainStackNode *push(ChainStackNode *node, int data) 
    ChainStackNode *s = (ChainStackNode *) malloc(sizeof(ChainStackNode));
    s->data = data;
    s->next = node->next;
    node->next = s;
    return node;


// 栈顶元素出栈(注意使用 getTop 保存栈顶元素)
ChainStackNode *pop(ChainStackNode *node) 
    if (stackIsEmpty(node)) 
        printf("栈已空\\n");
        return node;
     else 
        ChainStackNode *temp = node->next;
        node->next = temp->next;
        printf("出栈元素值为 %c\\n", temp->data);
        free(temp);
        return node;
    


// 获取栈顶元素
int getTop(ChainStackNode *node) 
    if (stackIsEmpty(node)) 
        printf("栈已空\\n");
        return -999;
     else 
        ChainStackNode *p = node->next;
        return p->data;
    


void printStack(ChainStackNode *node) 
    printf("\\n----- 当前栈 -----\\n");
    ChainStackNode *temp = node->next;
    while (temp != NULL) 
        printf("%c\\n", temp->data);
        temp = temp->next;
    
    printf("----- 当前栈 -----\\n\\n");


int main() 
    ChainStackNode *node;
    node = initStack();
    push(node, '1');
    push(node, 'c');
    push(node, '2');
    push(node, 'o');
    printStack(node);
    pop(node);
    printStack(node);
    printf("栈顶元素:%c", getTop(node));

2 队列

2.1 队列的顺序存储实现

#include<cstdio>

#define MaxSize 5
typedef struct 
    int data[MaxSize];
    int front, rear;
 SqQueue;

void initQueue(SqQueue &Q) 
    Q.front = Q.rear = 0;
    for (int i = 0; i < MaxSize; i++) 
        Q.data[i] = 0;
    


void enQueue(SqQueue &Q, int x) 
    if ((Q.rear + 1) % MaxSize == Q.front) 
        printf("队满\\n");
     else 
        Q.data[Q.rear] = x;
        // 队尾指针加 1 取模
        Q.rear = (Q.rear + 1) % MaxSize;
        printf("%d 入队成功\\n", x);
    


void deQueue(SqQueue &Q) 
    if (Q.rear == Q.front) 
        printf("队列为空\\n");
     else 
        printf("出队元素值为:%d\\n", Q.data[Q.front]);
        Q.data[Q.front] = 0;
        // 队头指针加 1 取模
        Q.front = (Q.front + 1) % MaxSize;
    


int countNodeNum(SqQueue s) 
    return (s.rear + MaxSize - s.front) % MaxSize;


void printQueue(SqQueue s) 
    printf("----- 当前队列 -----\\n");
    printf("元素个数为 %d\\n", countNodeNum(s));
    printf("队头 %d,队尾 %d(从上至下由 0 到 n)\\n", s.front, s.rear);
    for (int i = 0; i < MaxSize; i++) 
        printf("%d\\n", s.data[i]);
    


int main() 
    SqQueue sq;
    initQueue(sq);
    enQueue(sq, 1);
    enQueue(sq, 2);
    enQueue(sq, 3);
    enQueue(sq, 4);
    enQueue(sq, 5);
    deQueue(sq);
    enQueue(sq, 6);
    printQueue(sq);

2.2 队列的链式存储实现

#include <stdio.h>
#include <malloc.h>

// 这里灵活定义队列元素的数据类型,因为后续可能将树的结点的指针作为数据类型
typedef int queueElementDataType;
// typedef BinaryTreeNode *queueElementDataType;

// 自定义队列元素结构体
struct myQueueElement 
    queueElementDataType data;
    struct myQueueElement *next;
;
typedef struct myQueueElement QueueElement;
// 自定义队列结构体
struct myQueue 
    QueueElement *front, *rear;
;
typedef struct myQueue Queue;

Queue *initQueue() 
    QueueElement *queueElement = (QueueElement *) malloc(sizeof(QueueElement));
    Queue *queue = (Queue *) malloc(sizeof(Queue));
    // 初始化时 front rear 都指向头结点
    queue->front = queue->rear = queueElement;
    queue->front->next = NULL;
    return queue;


// 返回入队后的队列
Queue *enQueue(Queue *queue, queueElementDataType x) 
    QueueElement *s = (QueueElement *) malloc(sizeof(QueueElement));
    s->data = x;
    s->next = NULL;
    // 将新节点入队
    queue->rear->next = s;
    // 将尾指针后移
    queue->rear = s;
    return queue;


// 返回出队后的队列
Queue *deQueue(Queue *queue) 
    if (queue->front == queue->rear) 
        printf("队列为空\\n");
     else 
        // temp 为队头结点
        QueueElement *temp = queue->front->next;
        queue->front->next = temp->next;
        // 如果此时出队的结点刚好是最后一个结点
        if (temp == queue->rear) 
            // 那么在修改头结点的指向后,还要将尾指针指向头结点
            queue->rear = queue->front;
        
        free(temp);
    
    return queue;


queueElementDataType getFirstElementData(Queue *queue) 
    return queue->front->next->data;


void printQueue(Queue *queue) 
    printf("----- 当前队列 -----\\n");
    printf("从上至下代表从队头到队尾\\n");
    // temp 为队头元素
    QueueElement *temp = queue->front->next;
    while (temp != NULL) 
        // 这里需要根据 queueElementDataType 的类型来决定如何打印
        printf("%d\\n", temp->data);
        temp = temp->next;
    


int main() 
    Queue *queue;
    queue = initQueue();
    queue = enQueue(queue, 1);
    queue = enQueue(queue, 2);
    queue = enQueue(queue, 3);
    queue = enQueue(queue, 4);
    printQueue(queue);
    queue = deQueue(queue);
    printQueue(queue);
    queue = enQueue(queue, 5);
    printQueue(queue);

例 用不带头结点的单链表存储队列,其头指针指向队头结点,尾指针指向队尾结点,则在进行出队操作时(队头、队尾指针都可能要修改)

一般只需修改队头指针,不过当队列里面只有一个元素时,则需要同时修改头尾指针

3 栈和队列的应用(栈和队列的共同点:只允许在端点处插入和删除元素)

3.1 括号匹配

遇到左括号就入栈遇到右括号,就“消耗”一个左括号

以下代码用到了 1.2 栈的链式存储实现 中编写的基本操作

bool bracketCheck(char chars[], int length) 
    ChainStackNode *S;
    S = initStack();
    for (int i = 0; i < length; i++) 
        if (chars[i] == '(' || chars[i] == '[' || chars[i] == '') 
            // 扫描左括号,入栈
            S = push(S, chars[i]);
            printStack(S);
         else 
            // 扫描到右括号,且当前为栈空
            if (stackIsEmpty(S)) 
                printf("匹配失败");
                return false;
            
            int topElem = getTop(S);
            // 栈顶元素出栈
            S = pop(S);
            if (chars[i] == '(' && topElem != ')') 
                printf("匹配失败");
                return false;
            
            if (chars[i] == '' && topElem != '') 
                printf("匹配失败");
                return false;
            
            if (chars[i] == '[' && topElem != ']') 
                printf("匹配失败");
                return false;
            
        
    
    if (stackIsEmpty(S)) 
        printf("匹配成功");
        return true;
     else 
        printf("匹配失败");
        return false;
    


int main() 
    char chars[100] = '(', '(', '(', ')', ')'以上是关于栈和队列的主要内容,如果未能解决你的问题,请参考以下文章

数据结构(C语言版) 栈和队列 算法设计Demo6

恋上数据结构队列 Queue

恋上数据结构队列 Queue

使用带有头尾节点的单链表实现队列

栈和队列

栈和队列