数据结构笔记#栈

可以说线性表的一个具体应用就是栈,可能看完以下代码你觉得这是什么嘛有什么卵用啊,但是栈在现实生活的中的应用,或者说这种概念的应用是非常广泛的。

比如说各种浏览器的返回上一级功能。

栈与线性表最大的差别就是它对数据的操控是受限的,遵守Last in First out(LIFO)“后进先出原则”的数据结构都可以叫栈。

栈一般长这个样子(美工欠下了3.5个亿带着他的小姨子跑了!)

右边是我们对线性表之单链表的正常理解,数据从表头到表尾依次排放。

左边是栈的特性,处于上层的元素(较新)叫top,处于底部的元素(最先放进去的那个)叫bottom。

这里注意一下top指针指向的位置,是一个空白的位置,而不是最顶层的那个数据。

而bottom指针则一直指向最底层的那个数据。

对栈的常见操作有push(入栈,将数据放入栈)和pop(出栈,将数据提取出来)。

这两个操作只能影响最顶层的元素。

以下是我的具体的代码实现,实现的方式有很多种,以下仅供参考。

 Github

首先是栈的头文件.h

Stack.h

声明一下结构体及函数。

链表一样,栈你可以搞成链式也可以搞成顺序的,这里我用了顺序存储结构,方便操作。

 1 #ifndef _STACK_H_
 2 #define _STACK_H_
 3 
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6 
 7 //以下两个数据大小视实际情况而定
 8 //初始栈容量
 9 #define STACK_INIT_SIZE 10
10 //每次扩容的增量
11 #define STACKINCREMENT 10
12 
13 typedef int DataType;
14 
15 struct stack
16 {
17     //指向栈最顶上的元素的接下来一个位置
18     //表示新入栈的值可以放在指向的地方
19     DataType *Top;
20     //指向栈底部,最里面的元素
21     DataType *Bottom;
22     //表示了当前栈的容量
23     int stacksize;
24 };
25 typedef struct stack STACK;
26 
27 //新建栈
28 int InitStack(STACK *S);
29 
30 //销毁栈
31 int DestroyStack(STACK *S);
32 
33 //获取栈长度
34 int StackLength(STACK S);
35 
36 //获取栈顶部元素
37 int GetTop(STACK S, DataType *e);
38 
39 //Push操作,入栈,压栈
40 int Push(STACK *S, DataType e);
41 
42 //Pop操作,出栈
43 int Pop(STACK *S, DataType *e);
44 
45 //打印整表
46 int StackTraverse(STACK S);
47 
48 #endif

Stack.c

不知道为什么感觉栈的代码比链表的简单。。。直接都贴上来吧。

首先是初始化链表和销毁链表。

 1 int InitStack(STACK *S)
 2 {
 3     //创建出设定长度的顺序表,地址赋给bottom指针
 4     S->Bottom = (DataType*)malloc(STACK_INIT_SIZE*sizeof(DataType));
 5     if (!S->Bottom)
 6     {
 7         return 0;
 8     }
 9     S->stacksize = STACK_INIT_SIZE;
10     S->Top = S->Bottom;
11     return 1;
12 }
13 
14 int DestroyStack(STACK *S)
15 {
16     S->Top = NULL;
17     free(S->Bottom);
18     S->Bottom = NULL;
19     return 1;
20 }

然后是Push和Pop的函数,注释应该把代码解释的比较清楚了

 1 int Push(STACK *S, DataType e)
 2 {
 3     //当超出当前栈的容量时进行扩容
 4     //这里应该只有等于的情况
 5     //而不会大于
 6     if ((S->Top - S->Bottom) >= S->stacksize)
 7     {
 8         //realloc函数将开辟指定大小的储存空间
 9         //并将原来的数据全部移到这个新的储存空间
10         S->Bottom = (DataType*)realloc(S->Bottom, (S->stacksize + STACKINCREMENT)*sizeof(DataType));
11         if (!S->Bottom)
12         {
13             return 0;
14         }
15         //由于重新开辟了空间
16         //需要重新根据bottom指针的位置指定top
17         S->Top = S->Bottom + S->stacksize;
18         //最后增加当前栈容量
19         S->stacksize += STACKINCREMENT;
20     }
21     //再把入栈的数据存放好
22     *(S->Top++) = e;
23     return 1;
24 }
25 
26 int Pop(STACK *S, DataType *e)
27 {
28     if (S->Bottom == S->Top)
29     {
30         printf("Empty Stack!Can not pop!
");
31         return 0;
32     }
33     //top指针先减1再取值
34     *e = *(--S->Top);
35     return 1;
36 }

然后是其他一些奇奇怪怪的“辅助”函数

 1 int StackLength(STACK S)
 2 {
 3     return  S.Top - S.Bottom;
 4 }
 5 
 6 int GetTop(STACK S, DataType *e)
 7 {
 8     if (S.Bottom != S.Top)
 9     {
10         //由于top指向的是最顶上元素的下一个位置
11         //所以取出最顶上元素的时候
12         //要把top减去1
13         *e = *(S.Top - 1);
14         return 1;
15     }
16     return 0;
17 }

最后是打印整个栈的数据的函数

 1 int StackTraverse(STACK S)
 2 {
 3     int timer = 0;
 4     int *cur=S.Bottom;
 5     if (S.Bottom ==S.Top)
 6     {
 7         printf("Empty!
");
 8         return 1;
 9     }
10     while (cur < S.Top)
11     {
12         printf("%d) ", timer++);
13         printf("%d
", *(cur++));
14     }
15     return 1;
16 }

最后随便写个main函数测试一下

Stacktest.c

 1 #include"Stack.h"
 2 
 3 int main()
 4 {
 5     STACK s;
 6     int input=0;
 7     int output = 0;
 8     
 9     InitStack(&s);
10     StackTraverse(s);
11 
12     while(scanf("%d",&input) && input!=999)
13     {
14         Push(&s, input);
15     }
16     StackTraverse(s);
17     printf("Length: %d
", StackLength(s));;
18 
19     if (Pop(&s, &output))
20     {
21         printf("Poped : %d
", output);
22     }
23 
24     DestroyStack(&s);
25     return 0;
26 }
Stacktest.c

不同人的代码差别是很大的。。。但数据结构代码又没有一个标准,适和自己的需求就好,我也不敢确定我这么写最好。

如果感兴趣的话可以用栈做一个简单的计算器程序,用于计算比如

(3+(3-2))*10 = ?

这种的复合计算。

具体实现方法,我还在摸索。。

原文地址:https://www.cnblogs.com/makejeffer/p/4808142.html