本文主要是数据结构——栈的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows | windows11 |
Ubuntu | Ubuntu16.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
SecureCRT | Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日 |
开发板 | 正点原子 i.MX6ULL Linux阿尔法开发板 |
uboot | NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03) |
linux内核 | linux-4.15(NXP官方提供) |
STM32开发板 | 正点原子战舰V3(STM32F103ZET6) |
点击查看本文参考资料
点击查看相关文件下载
一、栈的概念
栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈)。
根据栈的定义,可以想象,水杯可以想象为一个栈,接水的时候相当于元素入栈,倒水的时候相当于元素出栈,没有水的时候就相当于空栈。
栈的特点是后进先出( LIFO ),它是一种特殊的线性存储结构,顺序结构和链式结构都可以实现栈,使用顺序结构实现的栈称为顺序栈,使用链式结构实现的栈称为链式栈。两种实现方式的区别仅限于数据元素在实际物理空间上存放的相对位置,顺序栈底层采用的是数组,链栈底层采用的是链表。
二、顺序栈
1.存储结构
顺序栈,即用顺序表实现栈存储结构。顺序表(底层实现是数组)和栈的存储数据的方式非常想似,只不过栈对数据的存取过程有特殊的限制,而顺序表没有。
2.结构体实现
可以把顺序栈看做是顺序表的一种,具有顺序表同样的存储结构,由数组定义,配合用数组下标表示的栈顶指针 top (相对指针)完成各种操作。顺序栈数据类型定义的 C 语言实现如下:
1 2 3 4 5 6 7 8
| typedef int data_t;
typedef struct { data_t *data; int maxlen; int top; }seqstack;
|
3.顺序栈基本操作
相关的源代码可以在这里下载:
3.1创建顺序栈
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
seqstack * seqstack_create(int len) { seqstack * S; if ((S =(seqstack *)malloc(sizeof(seqstack))) == NULL) { printf("seqstack malloc failed!\n"); return NULL; } if ((S->data = (data_t *)malloc(len * sizeof(data_t)))==NULL) { printf("seqstack data malloc data failed!\n"); free(S); return NULL; } memset(S->data, 0, len * sizeof(data_t)); S->maxlen = len; S->top = -1;
return S; }
|
3.2栈状态检测
3.2.1栈是否为空
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
int seqstack_empty(seqstack * S) { if (S == NULL) { printf("seqstack is not existed!\n"); return -1; } if(S->top == -1) return 1; else return 0; }
|
3.2.2栈是否已满
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
int seqstack_full(seqstack * S) { if (S == NULL) { printf("seqstack is not existed!\n"); return -1; } if(S->top == S->maxlen-1) return 1; else return 0; }
|
3.3数据入栈
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
int seqstack_push(seqstack * S, data_t value) { if (S == NULL) { printf("seqstack is not existed!\n"); return -1; } if (S->top == S->maxlen-1) { printf("seqstack is full!\n"); return -1; } S->top++; S->data[S->top] = value;
return 0; }
|
3.4数据出栈
【注意】这里出栈的时候不要做栈是否存在以及是否为空的判断,这两个判断若是有返回值的话程序会认为返回值就是出栈的元素,所以栈的存在性以及是否为空,要在使用出栈函数前进行判断。
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
data_t seqstack_pop(seqstack * S) { S->top--; return (S->data[S->top+1]); }
|
3.5清空栈
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
int seqstack_clear(seqstack * S) { if (S == NULL) { printf("seqstack is not existed!\n"); return -1; } S->top = -1; return 0; }
|
3.6释放顺序栈
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
int seqstack_free(seqstack * S) { if (S == NULL) { printf("seqstack is not existed!\n"); return -1; } if (S->data != NULL) { free(S->data); } free(S); printf("seqstack free completed!\n");
return 0; }
|
3.7显示顺序栈
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
int seqstack_show(seqstack * S) { int i = 0; if (S == NULL) { printf("seqstack is not existed!\n"); return -1; } if (S->top == -1) { printf("seqstack is empty!\n"); return -1; } printf("seqstack: "); while(i <= S->top) { printf("%d ", S->data[i]); i++; } puts(""); return 0; }
|
三、链式栈
1.存储结构
当我们固定单链表的一端,只在一段进行操作,便构成了栈,我们可以将链表头部作为栈顶的一端,这样可以避免在实现数据入栈”和 出栈 操作时做大量遍历链表的耗时操作。
这样就意味着我们需要在头节后进行节点的插入和删除来完成入栈和出栈。
2.结构体实现
我们通过单链表来实现栈,这样其实它还是一个单链表,仅仅是限制了插入和删除节点的位置罢了,所以结构体可以像这样定义:
1 2 3 4 5 6 7
| typedef int data_t;
typedef struct slstack_node { data_t data; struct slstack_node *next; }slstacknode, * slstacklink;
|
3.链式栈的基本操作
相关的源代码可以在这里下载:
3.1链栈创建
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
slstacklink slstack_create() { slstacklink S; S = (slstacklink)malloc(sizeof(slstacknode)); if(S == NULL) { printf("slinked list stack malloc failed!\n"); return NULL; } S->data = 0; S->next = NULL; return S; }
|
3.2链栈释放
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
slstacklink slstack_free(slstacklink S) { slstacklink p; if (S == NULL) { printf("slinked stack is not existed!\n"); return NULL; } printf("slinked stack free:"); while(S != NULL) { p = S; printf("%d ", p->data); S = S->next; free(p); } puts(""); return NULL; }
|
3.3链栈显示
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
int slstack_show(slstacklink S) { slstacklink p; if (S == NULL) { printf("slinked stack is not existed!\n"); return -1; } if (S->next == NULL) { printf("slinked stack is empty!\n"); return -1; } p = S; printf("slinked stack:"); while(p->next != NULL) { printf("%d ", p->next->data); p = p->next; } puts(""); return 0; }
|
3.4链栈状态
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
int slstack_empty(slstacklink S) { if (S == NULL) { printf("slinked stack is not existed!\n"); return -1; } if(S->next == NULL) return 1; else return 0; }
|
3.5数据入栈
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
int slstack_push(slstacklink S, data_t value) { slstacklink p; if (S == NULL) { printf("slinked stack is not existed!\n"); return -1; } p = (slstacklink)malloc(sizeof(slstacknode)); if(p == NULL) { printf("The new node malloc failed!\n"); return -1; } p->data = value; p->next = NULL; p->next = S->next; S->next = p; return 0; }
|
3.6数据出栈
【注意】这里出栈的时候不要做栈是否存在以及是否为空的判断,这两个判断若是有返回值的话程序会认为返回值就是出栈的元素,所以栈的存在性以及是否为空,要在使用出栈函数前进行判断。
点击查看函数实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
data_t slstack_pop(slstacklink S) { slstacklink p; data_t temp; p = S->next; S->next = p->next; temp = p->data; free(p); p = NULL; return temp; }
|