php中文网 | cnphp.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 585|回复: 0

[复制链接]

2670

主题

2677

帖子

9495

积分

管理员

Rank: 9Rank: 9Rank: 9

UID
1
威望
0
积分
6703
贡献
0
注册时间
2021-4-14
最后登录
2024-5-15
在线时间
673 小时
QQ
发表于 2022-2-24 08:37:20 | 显示全部楼层 |阅读模式
1 概念
栈是一种先进后出(FILO,First-In-Last-Out)的线性表,栈和队列非常相像,但是栈只能在栈顶插入(入栈)和删除(出栈)元素。同样,栈可以由链表和数组来实现。

对于栈这种数据结构,可以用浏览器来解释;比如我们可以把打开一个网站的过程看作是一次入栈操作,而返回上一次浏览的网站就相当于一次出栈操作。

树或栈这种数据结构用于解决 具有完全包含关系的问题;

2 基本操作
2.1 结构定义
实现栈需要引入1个变量top, 用来标记当前栈顶元素的位置。
[mw_shl_code=applescript,true]// 栈的结构定义(顺序表)
typedef struct Stack {
    int *data;
    int size, top; // size: 栈的容量,top: 标记栈顶元素的位置
} Stack;

// 栈的结构定义(链表)
typedef struct Node {
    int data;
    struct Node *next;
} Node;

typedef struct Stack {
    Node *top;
    int length;
} Stack;[/mw_shl_code]
2.2 入栈(top+1)
判断当前栈是否已满,能否继续插入元素;
栈顶标记 top 后移一位;
将新元素插入到当前栈顶标记的位置;
2.3 出栈(top-1)
判断当前栈是否为空,能否继续删除元素;
栈顶标记 top 前移一位;
3 代码演示
3.1 数组栈
[mw_shl_code=applescript,true]#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define COLOR(a, b) "\033[" #b "m" a "\033[0m"
#define RED(a) COLOR(a, 31)
#define GREEN(a) COLOR(a, 32)

typedef struct Stack {
    int *data;
    int size, top; // size: 栈的容量,top: 虚拟栈顶指针
} Stack;

Stack *init(int);       // 初始化栈空间
int top(Stack *);       // 获取栈顶元素
int empty(Stack *);     // 判断栈空间是否为空
int push(Stack *, int); // 入栈/压栈
int pop(Stack *);       // 出栈/弹栈
void clear(Stack *);    // 清空栈空间
void output(Stack *);   // 遍历栈空间元素
int expand(Stack *);    // 扩容


int main() {
    srand(time(0));
    #define MAX_OP 20
    Stack *s = init(1);
    for (int i = 0; i < MAX_OP; i++) {
        int op = rand() % 4;
        int val = rand() % 100;
        switch (op) {
            case 0:
            case 1:
            case 2: {
                printf("push %d to the stack = %d\n", val, push(s, val));
            } break;
            case 3: {
                if (!empty(s)) {
                    printf("pop %d from the stack = ", top(s));
                    printf("%d\n", pop(s));
                }
            } break;
        }
        output(s), printf("\n");
    }
    #undef MAX_OP

    return 0;
}

Stack *init(int n) {
    Stack *s = (Stack *)malloc(sizeof(Stack));
    s->data = (int *)malloc(sizeof(int) * n);
    s->size = n;
    s->top = -1;    // 表示栈空间中没有元素
    return s;
}

int top(Stack *s) {
    return s->data[s->top];
}

int empty(Stack *s) {
    return s->top == -1;
}

int push(Stack *s, int val) {
    if (s == NULL) return 0;
    if (s->top == s->size -1) {
        if (!expand(s)) {
            printf(RED("fail to expand!\n"));
            return 0;
        }
        printf(GREEN("success to expand! the new size = %d\n"), s->size);
    }
    s->data[++(s->top)] = val;
    return 1;
}

int pop(Stack *s) {
    if (s == NULL) return 0;
    if (empty(s)) return 0;
    s->top -= 1;
    return 1;
}

void clear(Stack *s) {
    if (s == NULL) return ;
    free(s->data);
    free(s);
    return ;
}

void output(Stack *s) {
    if (s == NULL) return ;
    printf("Stack(%d) : [", s->top + 1);
    for (int i = 0; i <= s->top; i++) {
        i && printf(", ");
        printf("%d", s->data);
    }
    printf("]\n");
    return ;
}

int expand(Stack *s) {
    int extr_size = s->size;
    int *temp;
    while (extr_size) {
        temp = (int *)realloc(s->data, sizeof(int) * (s->size + extr_size));
        if (temp != NULL) break;
        extr_size >>= 1;
    }
    if (temp == NULL) return 0;
    s->data = temp;
    s->size += extr_size;
    return 1;
}[/mw_shl_code]
3.2 链栈
[mw_shl_code=applescript,true]#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

typedef struct Stack {
    Node *top;
    int length;
} Stack;

Node *getNewNode(int);
Stack *init_stack();
void clear(Stack *);
int empty(Stack *);
int push(Stack *, int);
int pop(Stack *);
void output(Stack *);
int top(Stack *);

int main() {
    srand(time(0));
    #define MAX_OP 20
    Stack *s = init_stack();
    for (int i = 0; i < MAX_OP; i++) {
        int op = rand() % 4;
        int val = rand() % 100;
        switch (op) {
            case 0:
            case 1:
            case 2: {
                printf("push %d to the Stack = %d\n", val, push(s, val));
            } break;
            case 3: {
                if (!empty(s)) {
                    printf("pop %d from the Stack = ", top(s));
                    printf("%d\n", pop(s));
                }
            } break;
        }
        output(s), printf("\n");
    }
    #undef MAX_OP
    clear(s);
    return 0;
}

Node *getNewNode(int val) {
    Node *p = (Node *)malloc(sizeof(Node));
    p->data = val;
    p->next = NULL;
    return p;
}

Stack *init_stack() {
    Stack *s = (Stack *)malloc(sizeof(Stack));
    s->top = NULL;
    s->length = 0;
    return s;
}

void clear(Stack *s) {
    if (s == NULL) return;
    Node *p = s->top, *q;
    while (p != NULL) {
        q = p->next;
        free(p);
        p = q;
    }
    free(s);
    return;
}

int empty(Stack *s) {
    return s->top == NULL;
}

int top(Stack *s) {
    return s->top->data;
}

int push(Stack *s, int val) {
    if (s == NULL) return 0;
    Node *p = getNewNode(val);
    p->next = s->top;
    s->top = p;
    s->length += 1;
    return 1;
}

int pop(Stack *s) {
    if (s == NULL) return 0;
    if (empty(s)) return 0;
    Node *p = s->top;
    s->top = p->next;
    free(p);
    s->length -= 1;
    return 1;
}

void output(Stack *s) {
    if (s == NULL) return;
    printf("Stack[%d] : ", s->length);
    for (Node *p = s->top; p; p = p->next) {
        p != s->top && printf(" ");
        printf("%d", p->data);
    }
    printf("\n");
    return;
}[/mw_shl_code]
4 应用
4.1 数列翻转
将数列中的元素依次入栈;
将栈顶元素依次出栈,直到栈为空为止;
4.2 表达式中的括号匹配
依次遍历表达式中的字符,当该字符为左括号时,就入栈;当该字符为右括号时,就出栈;
在整个表达式遍历结束时,且当前栈为空,则括号匹配成功,否则,括号匹配失败;





上一篇:DevOpts 前端开发和 Spug
下一篇:利用信号量semaphore实现两个进程读写同步 Linux C
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|php中文网 | cnphp.com ( 赣ICP备2021002321号-2 )

GMT+8, 2024-5-15 18:21 , Processed in 0.158248 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

申明:本站所有资源皆搜集自网络,相关版权归版权持有人所有,如有侵权,请电邮(fiorkn@foxmail.com)告之,本站会尽快删除。

快速回复 返回顶部 返回列表