1 //栈,先进后出、后进先出特性
2
3
4 //顺序栈的静态存储结构需要预先定义或申请栈的存储空间,栈空间容量有限,一旦装满不能扩充,元素进栈会发生上溢现象
5 #define maxSize 100 //栈元素数据类型
6 typedef int SElemType;
7 typedef struct
8 {
9 SElemType elem[maxSize];
10 int top;
11 }SeqStack;
12
13 //顺序栈的动态存储结构
14 #define initSize 100 //栈空间初始大小
15 typedef int SElemType;//栈元素数据类型
16 typedef struct//顺序栈的结构定义
17 {
18 SElemType *elem;//栈元素存储数组
19 int maxSIze, top;//栈空间最大容量及栈顶指针(下标)
20 }SeqStack;
21 //动态顺序栈初始化
22 void InitStack(SeqStack& S)
23 {//建立一个最大尺寸为initSize的空栈,若分配不成功则执行错误处理
24 S.elem = new SElemType[initSize];
25 if(!S.elem){cerr<<"存储分配失败!\n"; exit(1);}
26 S.maxSize = initSIze;
27 S.top = -1;//栈空情形,因为向量下标从0开始,栈空时应该S.top < 0,因此空栈时栈顶指针S.top == -1
28 }
29
30 //动态顺序栈进栈操作的实现
31 void Push(SeqStack& s, SelemType x)
32 {
33 if(StackFull(S))//栈满则做溢出处理
34 OverflowProcess(S);
35 S.elem[++S.top] = x;//栈顶指针先加1,再进栈
36 }
37 //动态顺序栈溢出处理,扩充栈的内存空间
38 void OverflowProcess(SeqStack S)
39 {
40 SElemType *newArray = new SElemType[S.maxSize*2];
41 if(!newArray){cerr<<"存储分配失败!\n"; exit(1);}
42 for(int i=0; i<=S.top; i++)
43 newArray[i] = S.elem[i];
44 S.maxSize = 2*S.maxSize;//按2*S.maxSize大小申请新的连续存储空间,
45 delete []S.elem;//把原来存储空间中存的所有栈元素转移到新的存储空间后释放原来的存储空间
46 S.elem = newArray;//让S.elem指向新的存储空间
47 }
48 //顺序栈退栈操作的实现 先取出栈顶指针所指示栈顶的元素,再让栈顶指针减1,
49 int Pop(SeqStack& S, SElemType& x)
50 {//退栈:若栈不空则函数通过引用型参数x返回栈顶元素的值同时栈顶指针减1,函数返回1;否则函数返回0,且x的值不可引用
51 if(S.top == -1)//判栈空否,若栈空则函数返回0
52 return 0;
53 x = S.elem[S.top--];//栈顶指针减1
54 return 1;//退栈成功,函数返回1
55 }
56 //读取栈顶元素的值
57 int GetTop(SeqStack& S, SElemType& x)
58 {//若函数不空则函数返回栈顶元素的值且函数返回1,否则函数返回0
59 if(S.top == -1)//判栈空否,若栈空则函数返回0
60 return 0;
61 x = S.elem[S.top];//返回栈顶元素
62 return 1;
63 }
64 //判空,函数测试栈S空否。若栈空,则函数返回1,否则函数返回0
65 int StackEmpty(SeqStack& S)
66 {
67 return S.top == -1;//函数返回布尔式S.top == -1的运算结果
68 }
69 //判栈是否满
70 int StackFull(SeqStack& S)
71 {//函数测试栈S满否,若栈满,则函数返回1,否则函数返回0
72 return S.top == S.maxStack;
73 }
74 //判断栈的长度
75 int StackSize(SeqStack& S)
76 {
77 return S.top+1;//函数返回栈S的长度,即栈S中的元素个数
78 }
双栈共享同一栈空间
81 //当程序同时使用两个栈时,定义一个足够大的栈空间Vector[maxSize],并将两个栈设为0号栈和1号栈。该空间的两端分别设为两个站得栈底,
82 //用b[0](=-1)和b[1](=maxSize)指示。
83 //进栈情形:对于0号栈,每次进栈时栈顶指针t[0]加1;对于1号栈,每次进栈时栈顶指针t[1]减1。当两个栈的栈顶指针相遇,
84 //即t[0] + 1 == t[1]才算栈满
85 //退栈情形:对于0号栈,每次退栈时栈顶指针t[0]减1;对于1号栈,每次退栈时栈顶指针t[1]加1.只有当栈顶指针退到栈底才算栈空。
86 //两栈的大小可变。
87
88 //两栈共享同一栈空间时的进栈操作
89 int push(DualStack& DS, SElemType x, int d)
90 {//在d所指示的栈中插入元素x。d=0,插在0号线;d=1,插在1号线,若插入成功,函数返回1,否则返回0
91 if(DS.t[0]+1 == DS.t[1] || d != 0 && d !=1)
92 return 0;
93 if(d == 0)
94 DS.t[0]++;//栈顶指针加1
95 else
96 DS.t[1]--;//栈尾减1
97 DS.Vector[DS.t[d]] = x;//进栈
98 return 1;
99 }
100 //两栈共享同一空间时的退栈操作
101 int pop(DualStack& DS, SElemType& x, int d)
102 {//在d所指示的栈中退出栈顶元素,通过引用型参数x返回。d=0,从0号栈退栈;d=1,从1号栈退栈。若退栈成功,函数返回1,否则函数返回0
103 if(d != 0 && d != 1 || DS.t[d] == DS.b[d])
104 return 0;
105 x= DS.Vector[DS.t[d]];//取出栈顶元素的值
106 if(d == 0)//栈顶指针减1
107 DS.t[0]--;
108 else
109 DS.t[1]++;
110 return 1;
111 }
链式栈
116 //链式栈
117 //采用链式栈来表示一个栈,便于结点的插入和删除,在程序中同时使用多个栈的情况下,用链接表示不仅能提高速率,还可以达到共享存储
118 //空间的目的。链式栈的栈顶指针在栈表头结点,但实际的栈顶结点在头结点后面的首元结点。因此,新结点的插入和栈顶结点的删除都在链表
119 //的首元结点使用了一个链表的头指针来表示一个栈。对于同时使用多个栈的情形,只要声明一个链表指针向量,就能同时定义和使用多个
120 //链式栈,并且无需在运算时做存储空间的移动。
121
122 //链式栈的定义
123 typedef int SElemType;
124 typedef struct node
125 {
126 SElemType data;
127 struct node *link;
128 }LinkNode, *LinkStack ;
129
130 void InitStack(LinkStack& S)
131 {//链式栈初始化:置栈顶指针,即链表头指针为空
132 S = new LinkNode;//创建结点
133 if(!S){cerr<<"存储分配失败!\n"; exit(1);}
134 S->link = NULL;//栈顶置空
135 }
136 void Push(LinkStack& S, SElemType x)
137 {//进栈:将元素x插入到链式栈的栈顶,即链表头
138 LinkNode *p = new LinkNode;//创建新结点
139 if(!p){cer<<"存储分配失败!\n";exit(1);}
140 p->data = x;
141 p->link = S->link;//新结点插入在链表头
142 S->link = p;
143 }
144 int Pop(LinkStack& S, SElemType& x)
145 {//退栈:若栈不空,删除栈顶结点并通过引用型参数x返回被删栈顶元素的值,若删除成功,函数返回1,否则函数返回0,此时x的值不可引用
146 if(S->link == NULL)//若栈空则不退栈,返回0
147 return 0;
148 LinkNode *p = S->link;//否则暂存栈顶元素
149 S->link = p->link;//栈顶指针退回到新的栈顶位置
150 x = p->data;//释放结点,返回退出元素的值
151 delete p;//
152 return 1;
153 }
154 int GetTop(LinkStack& S, SElemType& x)
155 {//读取栈顶:若栈不空,通过引用型参数x返回栈顶元素的值,且函数返回1,若栈空,函数返回0,此时x的值不可引用
156 if(S->link == NULL)return 0;//若栈空则返回0
157 x = S->link->data;//栈不空则返回栈顶元素的值
158 return 1;
159 }
160 int StackEmpty(LinkStack& S)
161 {//判断栈是否为空:若栈空,则函数返回1,否则函数返回0
162 return S->link == NULL;//返回S->link == NULL结果
163 }
164 int StackSize(LinkSize& S)
165 {//求栈的长度:计算栈元素个数
166 LinkNode *p = S->link;
167 int k=0;
168 while(p != NULL)//逐个结点计数
169 {
170 p = p->link;
171 k++;
172 }
173 return k;
174 }