概要
本章会先对栈的原理进行介绍,然后分别通过C/C++/Java三种语言来演示栈的实现示例。注意:本文所说的栈是数据结构中的栈,而不是内存模型中栈。内容包括:
1. 栈的介绍
2. 栈的C实现
3. 栈的C++实现
4. 栈的Java实现
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3562239.html
更多内容: 数据结构与算法系列 目录
栈的介绍
栈(stack),是一种线性存储结构,它有以下几个特点:
(01) 栈中数据是按照"后进先出(LIFO, Last In First Out)"方式进出栈的。
(02) 向栈中添加/删除数据时,只能从栈顶进行操作。
栈通常包括的三种操作:push、peek、pop。
push -- 向栈中添加元素。
peek -- 返回栈顶元素。
pop -- 返回并删除栈顶元素的操作。
1. 栈的示意图
栈中的数据依次是 30 --> 20 --> 10
2. 出栈
出栈前:栈顶元素是30。此时,栈中的元素依次是 30 --> 20 --> 10
出栈后:30出栈之后,栈顶元素变成20。此时,栈中的元素依次是 20 --> 10
3. 入栈
入栈前:栈顶元素是20。此时,栈中的元素依次是 20 --> 10
入栈后:40入栈之后,栈顶元素变成40。此时,栈中的元素依次是 40 --> 20 --> 10
下面介绍栈的实现,分别介绍C/C++/Java三种实现。
栈的C实现
共介绍4种C语言实现。
1. C语言实现一:数组实现的栈,并且只能存储int数据。
2. C语言实现二:单向链表实现的栈,并且只能存储int数据。
3. C语言实现三:双向链表实现的栈,并且只能存储int数据。
4. C语言实现四:双向链表实现的栈,能存储任意类型的数据。
1. C语言实现一:数组实现的栈,并且只能存储int数据
实现代码(array_stack.c)
1 #include <stdio.h>
2 #include <malloc.h>
3
4 /**
5 * C 语言: 数组实现的栈,只能存储int数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10
11 // 保存数据的数组
12 static int *arr=NULL;
13 // 栈的实际大小
14 static int count;
15
16 // 创建“栈”,默认大小是12
17 int create_array_stack(int sz)
18 {
19 arr = (int *)malloc(sz*sizeof(int));
20 if (!arr)
21 {
22 printf("arr malloc error!");
23 return -1;
24 }
25
26 return 0;
27 }
28
29 // 销毁“栈”
30 int destroy_array_stack()
31 {
32 if (arr)
33 {
34 free(arr);
35 arr = NULL;
36 }
37
38 return 0;
39 }
40
41 // 将val添加到栈中
42 void push(int val)
43 {
44 arr[count++] = val;
45 }
46
47 // 返回“栈顶元素值”
48 int peek()
49 {
50 return arr[count-1];
51 }
52
53 // 返回“栈顶元素值”,并删除“栈顶元素”
54 int pop()
55 {
56 int ret = arr[count-1];
57 count--;
58 return ret;
59 }
60
61 // 返回“栈”的大小
62 int size()
63 {
64 return count;
65 }
66
67 // 返回“栈”是否为空
68 int is_empty()
69 {
70 return size()==0;
71 }
72
73 // 打印“栈”
74 void print_array_stack()
75 {
76 if (is_empty())
77 {
78 printf("stack is Empty
");
79 return ;
80 }
81
82 printf("stack size()=%d
", size());
83
84 int i=size()-1;
85 while (i>=0)
86 {
87 printf("%d
", arr[i]);
88 i--;
89 }
90 }
91
92
93 void main()
94 {
95 int tmp=0;
96
97 // 创建“栈”
98 create_array_stack(12);
99
100 // 将10, 20, 30 依次推入栈中
101 push(10);
102 push(20);
103 push(30);
104
105 //print_array_stack(); // 打印栈
106
107 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
108 tmp = pop();
109 printf("tmp=%d
", tmp);
110 //print_array_stack(); // 打印栈
111
112 // 只将“栈顶”赋值给tmp,不删除该元素.
113 tmp = peek();
114 printf("tmp=%d
", tmp);
115 //print_array_stack(); // 打印栈
116
117 push(40);
118 print_array_stack(); // 打印栈
119
120 // 销毁栈
121 destroy_array_stack();
122 }
运行结果:
tmp=30
tmp=20
stack size()=3
40
20
10
结果说明:该示例中的栈,是通过"数组"来实现的!
由于代码中已经给出了详细了注释,这里就不再对函数进行说明了。仅对主函数main的逻辑进行简单介绍。
(01) 在主函数main中,先将 "10, 20, 30"依次压入栈。此时,栈的数据是: 30 --> 20 --> 10
(02) 接着通过pop()返回栈顶元素;pop()操作并不会改变栈中的数据。此时,栈的数据依然是: 30 --> 20 --> 10
(03) 接着通过peek()返回并删除栈顶元素。peek操作之后,栈的数据是: 20 --> 10
(04) 接着通过push(40)将40压入栈中。push(40)操作之后,栈的数据是: 40 --> 20 --> 10
2. C语言实现二:单向链表实现的栈,并且只能存储int数据
实现代码(slink_stack.c)
1 #include <stdio.h>
2 #include <malloc.h>
3
4 /**
5 * C 语言: 单向链表实现的栈,只能存储int数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10
11 // 单向链表的“节点”
12 struct node {
13 int val;
14 struct node* next;
15 };
16
17 // 单向链表的“表头”
18 static struct node *phead=NULL;
19
20 // 创建节点,val为节点值
21 static struct node* create_node(int val)
22 {
23 struct node *pnode=NULL;
24 pnode = (struct node*)malloc(sizeof(struct node));
25 if (!pnode)
26 return NULL;
27 pnode->val = val;
28 pnode->next = NULL;
29
30 return pnode;
31 }
32
33 // 销毁单向链表
34 static int destroy_single_link()
35 {
36 struct node *pnode=NULL;
37
38 while (phead != NULL) {
39 pnode = phead;
40 phead = phead->next;
41 free(pnode);
42 }
43 return 0;
44 }
45
46 // 将val插入到链表的表头位置
47 static struct node* push(int val)
48 {
49 struct node *pnode = NULL;
50
51 pnode = create_node(val);
52 pnode->next = phead;
53 phead = pnode;
54
55 return phead;
56 }
57
58 // 删除链表的表头
59 static int pop()
60 {
61 if (!phead)
62 {
63 printf("remove failed! link is empty!");
64 return -1;
65 }
66
67 int ret;
68 struct node *pnode;
69 ret = phead->val;
70 pnode = phead;
71 phead = phead->next;
72 free(pnode);
73
74 return ret;
75 }
76
77 // 返回链表的表头节点的值
78 static int peek()
79 {
80 if (!phead)
81 {
82 printf("peek failed! link is empty!");
83 return -1;
84 }
85
86 return phead->val;
87 }
88
89 // 返回链表中节点的个数
90 static int size()
91 {
92 int count=0;
93 struct node *pnode=phead;
94
95 while (pnode != NULL) {
96 pnode = pnode->next;
97 count++;
98 }
99 return count;
100 }
101
102 // 链表是否为空
103 static int is_empty()
104 {
105 return phead==NULL;
106 }
107
108 // 打印“栈”
109 static void print_single_link()
110 {
111 if (is_empty())
112 {
113 printf("stack is Empty
");
114 return 0;
115 }
116
117 printf("stack size()=%d
", size());
118
119 struct node *pnode=NULL;
120
121 while (phead != NULL) {
122 printf("%d
", phead->val);
123 pnode = phead;
124 phead = phead->next;
125 free(pnode);
126 }
127 }
128
129 void main()
130 {
131 int tmp=0;
132
133 // 将10, 20, 30 依次推入栈中
134 push(10);
135 push(20);
136 push(30);
137
138 //print_single_link(); // 打印栈
139
140 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
141 tmp = pop();
142 printf("tmp=%d
", tmp);
143 //print_single_link(); // 打印栈
144
145 // 只将“栈顶”赋值给tmp,不删除该元素.
146 tmp = peek();
147 printf("tmp=%d
", tmp);
148 //print_single_link(); // 打印栈
149
150 push(40);
151 print_single_link(); // 打印栈
152
153 // 销毁栈
154 destroy_single_link();
155 }
代码说明:"运行结果" 以及 "主函数main的逻辑"都和"C语言实现一"的一样。不同的是,该示例中的栈是通过单向链表实现的。
3. C语言实现三:双向链表实现的栈,并且只能存储int数据
实现代码
双向链表的头文件(double_link.h)
1 #ifndef _DOUBLE_LINK_H
2 #define _DOUBLE_LINK_H
3
4 // 新建“双向链表”。成功,返回表头;否则,返回NULL
5 extern int create_dlink();
6 // 撤销“双向链表”。成功,返回0;否则,返回-1
7 extern int destroy_dlink();
8
9 // “双向链表是否为空”。为空的话返回1;否则,返回0。
10 extern int dlink_is_empty();
11 // 返回“双向链表的大小”
12 extern int dlink_size();
13
14 // 获取“双向链表中第index位置的元素的值”。成功,返回节点值;否则,返回-1。
15 extern int dlink_get(int index);
16 // 获取“双向链表中第1个元素的值”。成功,返回节点值;否则,返回-1。
17 extern int dlink_get_first();
18 // 获取“双向链表中最后1个元素的值”。成功,返回节点值;否则,返回-1。
19 extern int dlink_get_last();
20
21 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
22 extern int dlink_insert(int index, int value);
23 // 将“value”插入到表头位置。成功,返回0;否则,返回-1。
24 extern int dlink_insert_first(int value);
25 // 将“value”插入到末尾位置。成功,返回0;否则,返回-1。
26 extern int dlink_append_last(int value);
27
28 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1
29 extern int dlink_delete(int index);
30 // 删除第一个节点。成功,返回0;否则,返回-1
31 extern int dlink_delete_first();
32 // 删除组后一个节点。成功,返回0;否则,返回-1
33 extern int dlink_delete_last();
34
35 // 打印“双向链表”
36 extern void print_dlink();
37
38 #endif
双向链表的实现文件double_link.c)
1 #include <stdio.h>
2 #include <malloc.h>
3
4 /**
5 * c语言实现的双向链表
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10 // 双向链表节点
11 typedef struct tag_node
12 {
13 struct tag_node *prev;
14 struct tag_node *next;
15 int value;
16 }node;
17
18 // 表头。注意,表头不存放元素值!!!
19 static node *phead=NULL;
20 // 节点个数。
21 static int count=0;
22
23 // 新建“节点”。成功,返回节点指针;否则,返回NULL。
24 static node* create_node(int value)
25 {
26 node *pnode=NULL;
27 pnode = (node *)malloc(sizeof(node));
28 if (!pnode)
29 {
30 printf("create node error!
");
31 return NULL;
32 }
33 // 默认的,pnode的前一节点和后一节点都指向它自身
34 pnode->prev = pnode->next = pnode;
35 // 节点的值为value
36 pnode->value = value;
37
38 return pnode;
39 }
40
41 // 新建“双向链表”。成功,返回0;否则,返回-1。
42 int create_dlink()
43 {
44 // 创建表头
45 phead = create_node(-1);
46 if (!phead)
47 return -1;
48
49 // 设置“节点个数”为0
50 count = 0;
51
52 return 0;
53 }
54
55 // “双向链表是否为空”
56 int dlink_is_empty()
57 {
58 return count == 0;
59 }
60
61 // 返回“双向链表的大小”
62 int dlink_size() {
63 return count;
64 }
65
66 // 获取“双向链表中第index位置的节点”
67 static node* get_node(int index)
68 {
69 if (index<0 || index>=count)
70 {
71 printf("%s failed! the index in out of bound!
", __func__);
72 return NULL;
73 }
74
75 // 正向查找
76 if (index <= (count/2))
77 {
78 int i=0;
79 node *pnode=phead->next;
80 while ((i++) < index)
81 pnode = pnode->next;
82
83 // printf("%s %d i=%d, pnode->value=%d
",
84 // __func__, __LINE__, i, pnode->value);
85 return pnode;
86 }
87
88 // 反向查找
89 int j=0;
90 int rindex = count - index - 1;
91 node *rnode=phead->prev;
92 while ((j++) < rindex)
93 rnode = rnode->prev;
94
95 // printf("%s %d j=%d, rnode->value=%d
",
96 // __func__, __LINE__, j, rnode->value);
97 return rnode;
98 }
99
100 // 获取“第一个节点”
101 static node* get_first_node()
102 {
103 return get_node(0);
104 }
105
106 // 获取“最后一个节点”
107 static node* get_last_node()
108 {
109 return get_node(count-1);
110 }
111
112 // 获取“双向链表中第index位置的元素的值”。成功,返回节点值;否则,返回-1。
113 int dlink_get(int index)
114 {
115 node *pindex=get_node(index);
116 if (!pindex)
117 {
118 printf("%s failed!
", __func__);
119 return -1;
120 }
121
122 return pindex->value;
123
124 }
125
126 // 获取“双向链表中第1个元素的值”
127 int dlink_get_first()
128 {
129 return dlink_get(0);
130 }
131
132 // 获取“双向链表中最后1个元素的值”
133 int dlink_get_last()
134 {
135 return dlink_get(count-1);
136 }
137
138 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
139 int dlink_insert(int index, int value)
140 {
141 // 插入表头
142 if (index==0)
143 return dlink_insert_first(value);
144
145 // 获取要插入的位置对应的节点
146 node *pindex=get_node(index);
147 if (!pindex)
148 return -1;
149
150 // 创建“节点”
151 node *pnode=create_node(value);
152 if (!pnode)
153 return -1;
154
155 pnode->prev = pindex->prev;
156 pnode->next = pindex;
157 pindex->prev->next = pnode;
158 pindex->prev = pnode;
159 // 节点个数+1
160 count++;
161
162 return 0;
163 }
164
165 // 将“value”插入到表头位置
166 int dlink_insert_first(int value)
167 {
168 node *pnode=create_node(value);
169 if (!pnode)
170 return -1;
171
172 pnode->prev = phead;
173 pnode->next = phead->next;
174 phead->next->prev = pnode;
175 phead->next = pnode;
176 count++;
177 return 0;
178 }
179
180 // 将“value”插入到末尾位置
181 int dlink_append_last(int value)
182 {
183 node *pnode=create_node(value);
184 if (!pnode)
185 return -1;
186
187 pnode->next = phead;
188 pnode->prev = phead->prev;
189 phead->prev->next = pnode;
190 phead->prev = pnode;
191 count++;
192 return 0;
193 }
194
195 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
196 int dlink_delete(int index)
197 {
198 node *pindex=get_node(index);
199 if (!pindex)
200 {
201 printf("%s failed! the index in out of bound!
", __func__);
202 return -1;
203 }
204
205 pindex->next->prev = pindex->prev;
206 pindex->prev->next = pindex->next;
207 free(pindex);
208 count--;
209
210 return 0;
211 }
212
213 // 删除第一个节点
214 int dlink_delete_first()
215 {
216 return dlink_delete(0);
217 }
218
219 // 删除组后一个节点
220 int dlink_delete_last()
221 {
222 return dlink_delete(count-1);
223 }
224
225 // 撤销“双向链表”。成功,返回0;否则,返回-1。
226 int destroy_dlink()
227 {
228 if (!phead)
229 {
230 printf("%s failed! dlink is null!
", __func__);
231 return -1;
232 }
233
234 node *pnode=phead->next;
235 node *ptmp=NULL;
236 while(pnode != phead)
237 {
238 ptmp = pnode;
239 pnode = pnode->next;
240 free(ptmp);
241 }
242
243 free(phead);
244 phead = NULL;
245 count = 0;
246
247 return 0;
248 }
249
250 // 打印“双向链表”
251 void print_dlink()
252 {
253 if (count==0 || (!phead))
254 {
255 printf("stack is Empty
");
256 return ;
257 }
258
259 printf("stack size()=%d
", count);
260 node *pnode=phead->next;
261 while(pnode != phead)
262 {
263 printf("%d
", pnode->value);
264 pnode = pnode->next;
265 }
266 }
双向链表的测试程序(dlink_stack.c)
1 #include <stdio.h>
2 #include "double_link.h"
3
4 /**
5 * C 语言: 双向链表实现栈,只能存储int数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10 // 创建栈
11 int create_dlink_stack()
12 {
13 return create_dlink();
14 }
15
16 // 销毁栈
17 int destroy_dlink_stack()
18 {
19 return destroy_dlink();
20 }
21
22 // 将val添加到栈中
23 int push(int val)
24 {
25 return dlink_insert_first(val);
26 }
27
28 // 返回“栈顶元素值”
29 int peek()
30 {
31 return dlink_get_first();
32 }
33
34 // 返回“栈顶元素值”,并删除“栈顶元素”
35 int pop()
36 {
37 int ret = peek();
38 dlink_delete_first();
39 return ret;
40 }
41
42 // 返回“栈”的大小
43 int size()
44 {
45 return dlink_size();
46 }
47
48 // 返回“栈”是否为空
49 int is_empty()
50 {
51 return dlink_is_empty();
52 }
53
54 // 打印“栈”
55 void print_dlink_stack()
56 {
57 return print_dlink();
58 }
59
60 void main()
61 {
62 int tmp=0;
63
64 // 创建“栈”
65 create_dlink_stack();
66
67 // 将10, 20, 30 依次推入栈中
68 push(10);
69 push(20);
70 push(30);
71
72 //print_dlink_stack(); // 打印栈
73
74 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
75 tmp = pop();
76 printf("tmp=%d
", tmp);
77 //print_dlink_stack(); // 打印栈
78
79 // 只将“栈顶”赋值给tmp,不删除该元素.
80 tmp = peek();
81 printf("tmp=%d
", tmp);
82 //print_dlink_stack(); // 打印栈
83
84 push(40);
85 print_dlink_stack(); // 打印栈
86
87 // 销毁栈
88 destroy_dlink_stack();
89 }
代码说明:"运行结果" 以及 "主函数main的逻辑"都和前两个示例的一样。不同的是,该示例中的栈是通过双向链表实现的。
4. C语言实现四:双向链表实现的栈,能存储任意类型的数据
实现代码
双向链表的头文件(double_link.h)
1 #ifndef _DOUBLE_LINK_H
2 #define _DOUBLE_LINK_H
3
4 // 新建“双向链表”。成功,返回表头;否则,返回NULL
5 extern int create_dlink();
6 // 撤销“双向链表”。成功,返回0;否则,返回-1
7 extern int destroy_dlink();
8
9 // “双向链表是否为空”。为空的话返回1;否则,返回0。
10 extern int dlink_is_empty();
11 // 返回“双向链表的大小”
12 extern int dlink_size();
13
14 // 获取“双向链表中第index位置的元素”。成功,返回节点指针;否则,返回NULL。
15 extern void* dlink_get(int index);
16 // 获取“双向链表中第1个元素”。成功,返回节点指针;否则,返回NULL。
17 extern void* dlink_get_first();
18 // 获取“双向链表中最后1个元素”。成功,返回节点指针;否则,返回NULL。
19 extern void* dlink_get_last();
20
21 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
22 extern int dlink_insert(int index, void *pval);
23 // 将“value”插入到表头位置。成功,返回0;否则,返回-1。
24 extern int dlink_insert_first(void *pval);
25 // 将“value”插入到末尾位置。成功,返回0;否则,返回-1。
26 extern int dlink_append_last(void *pval);
27
28 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1
29 extern int dlink_delete(int index);
30 // 删除第一个节点。成功,返回0;否则,返回-1
31 extern int dlink_delete_first();
32 // 删除组后一个节点。成功,返回0;否则,返回-1
33 extern int dlink_delete_last();
34
35 #endif
双向链表的实现文件(double_link.c)
1 #include <stdio.h>
2 #include <malloc.h>
3
4
5 /**
6 * C 语言实现的双向链表,能存储任意数据。
7 *
8 * @author skywang
9 * @date 2013/11/07
10 */
11 // 双向链表节点
12 typedef struct tag_node
13 {
14 struct tag_node *prev;
15 struct tag_node *next;
16 void* p;
17 }node;
18
19 // 表头。注意,表头不存放元素值!!!
20 static node *phead=NULL;
21 // 节点个数。
22 static int count=0;
23
24 // 新建“节点”。成功,返回节点指针;否则,返回NULL。
25 static node* create_node(void *pval)
26 {
27 node *pnode=NULL;
28 pnode = (node *)malloc(sizeof(node));
29 if (!pnode)
30 {
31 printf("create node error!
");
32 return NULL;
33 }
34 // 默认的,pnode的前一节点和后一节点都指向它自身
35 pnode->prev = pnode->next = pnode;
36 // 节点的值为pval
37 pnode->p = pval;
38
39 return pnode;
40 }
41
42 // 新建“双向链表”。成功,返回0;否则,返回-1。
43 int create_dlink()
44 {
45 // 创建表头
46 phead = create_node(NULL);
47 if (!phead)
48 return -1;
49
50 // 设置“节点个数”为0
51 count = 0;
52
53 return 0;
54 }
55
56 // “双向链表是否为空”
57 int dlink_is_empty()
58 {
59 return count == 0;
60 }
61
62 // 返回“双向链表的大小”
63 int dlink_size() {
64 return count;
65 }
66
67 // 获取“双向链表中第index位置的节点”
68 static node* get_node(int index)
69 {
70 if (index<0 || index>=count)
71 {
72 printf("%s failed! index out of bound!
", __func__);
73 return NULL;
74 }
75
76 // 正向查找
77 if (index <= (count/2))
78 {
79 int i=0;
80 node *pnode=phead->next;
81 while ((i++) < index)
82 pnode = pnode->next;
83
84 return pnode;
85 }
86
87 // 反向查找
88 int j=0;
89 int rindex = count - index - 1;
90 node *rnode=phead->prev;
91 while ((j++) < rindex)
92 rnode = rnode->prev;
93
94 return rnode;
95 }
96
97 // 获取“第一个节点”
98 static node* get_first_node()
99 {
100 return get_node(0);
101 }
102
103 // 获取“最后一个节点”
104 static node* get_last_node()
105 {
106 return get_node(count-1);
107 }
108
109 // 获取“双向链表中第index位置的元素”。成功,返回节点值;否则,返回-1。
110 void* dlink_get(int index)
111 {
112 node *pindex=get_node(index);
113 if (!pindex)
114 {
115 printf("%s failed!
", __func__);
116 return NULL;
117 }
118
119 return pindex->p;
120
121 }
122
123 // 获取“双向链表中第1个元素的值”
124 void* dlink_get_first()
125 {
126 return dlink_get(0);
127 }
128
129 // 获取“双向链表中最后1个元素的值”
130 void* dlink_get_last()
131 {
132 return dlink_get(count-1);
133 }
134
135 // 将“pval”插入到index位置。成功,返回0;否则,返回-1。
136 int dlink_insert(int index, void* pval)
137 {
138 // 插入表头
139 if (index==0)
140 return dlink_insert_first(pval);
141
142 // 获取要插入的位置对应的节点
143 node *pindex=get_node(index);
144 if (!pindex)
145 return -1;
146
147 // 创建“节点”
148 node *pnode=create_node(pval);
149 if (!pnode)
150 return -1;
151
152 pnode->prev = pindex->prev;
153 pnode->next = pindex;
154 pindex->prev->next = pnode;
155 pindex->prev = pnode;
156 // 节点个数+1
157 count++;
158
159 return 0;
160 }
161
162 // 将“pval”插入到表头位置
163 int dlink_insert_first(void *pval)
164 {
165 node *pnode=create_node(pval);
166 if (!pnode)
167 return -1;
168
169 pnode->prev = phead;
170 pnode->next = phead->next;
171 phead->next->prev = pnode;
172 phead->next = pnode;
173 count++;
174 return 0;
175 }
176
177 // 将“pval”插入到末尾位置
178 int dlink_append_last(void *pval)
179 {
180 node *pnode=create_node(pval);
181 if (!pnode)
182 return -1;
183
184 pnode->next = phead;
185 pnode->prev = phead->prev;
186 phead->prev->next = pnode;
187 phead->prev = pnode;
188 count++;
189 return 0;
190 }
191
192 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
193 int dlink_delete(int index)
194 {
195 node *pindex=get_node(index);
196 if (!pindex)
197 {
198 printf("%s failed! the index in out of bound!
", __func__);
199 return -1;
200 }
201
202 pindex->next->prev = pindex->prev;
203 pindex->prev->next = pindex->next;
204 free(pindex);
205 count--;
206
207 return 0;
208 }
209
210 // 删除第一个节点
211 int dlink_delete_first()
212 {
213 return dlink_delete(0);
214 }
215
216 // 删除组后一个节点
217 int dlink_delete_last()
218 {
219 return dlink_delete(count-1);
220 }
221
222 // 撤销“双向链表”。成功,返回0;否则,返回-1。
223 int destroy_dlink()
224 {
225 if (!phead)
226 {
227 printf("%s failed! dlink is null!
", __func__);
228 return -1;
229 }
230
231 node *pnode=phead->next;
232 node *ptmp=NULL;
233 while(pnode != phead)
234 {
235 ptmp = pnode;
236 pnode = pnode->next;
237 free(ptmp);
238 }
239
240 free(phead);
241 phead = NULL;
242 count = 0;
243
244 return 0;
245 }
双向链表的测试程序(dlink_stack.c)
1 #include <stdio.h>
2 #include "double_link.h"
3
4 /**
5 * C 语言: 双向链表实现栈,能存储任意数据。
6 *
7 * @author skywang
8 * @date 2013/11/07
9 */
10 // 创建栈
11 int create_dlink_stack()
12 {
13 return create_dlink();
14 }
15
16 // 销毁栈
17 int destroy_dlink_stack()
18 {
19 return destroy_dlink();
20 }
21
22 // 将val添加到栈中
23 int push(void *p)
24 {
25 return dlink_insert_first(p);
26 }
27
28 // 返回“栈顶元素值”
29 void* peek()
30 {
31 return dlink_get_first();
32 }
33
34 // 返回“栈顶元素值”,并删除“栈顶元素”
35 void* pop()
36 {
37 void *p = peek();
38 dlink_delete_first();
39 return p;
40 }
41
42 // 返回“栈”的大小
43 int size()
44 {
45 return dlink_size();
46 }
47
48 // 返回“栈”是否为空
49 int is_empty()
50 {
51 return dlink_is_empty();
52 }
53
54
55 typedef struct tag_stu
56 {
57 int id;
58 char name[20];
59 }stu;
60
61 static stu arr_stu[] =
62 {
63 {10, "sky"},
64 {20, "jody"},
65 {30, "vic"},
66 {40, "dan"},
67 };
68 #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) )
69
70 static void print_stu(stu *p)
71 {
72 if (!p)
73 return ;
74
75 printf("id=%d, name=%s
", p->id, p->name);
76 }
77
78 void main()
79 {
80 stu *pval=NULL;
81
82 // 创建“栈”
83 create_dlink_stack();
84
85 // 将10, 20, 30 依次推入栈中
86 int i=0;
87 for (i=0; i<ARR_STU_SIZE-1; i++)
88 {
89 push(&arr_stu[i]);
90 }
91
92 // 将“栈顶元素”赋值给pval,并删除“栈顶元素”
93 pval = (stu*)pop();
94 //print_stu(pval) ;
95
96 // 只将“栈顶”赋值给pval,不删除该元素.
97 pval = peek();
98 //print_stu(pval) ;
99
100 push(&arr_stu[ARR_STU_SIZE-1]);
101
102
103 // 打印栈中的所有元素
104 while (!is_empty())
105 {
106 pval = pop();
107 print_stu(pval) ;
108 }
109
110 // 销毁栈
111 destroy_dlink_stack();
112 }
运行结果:
id=40, name=dan
id=20, name=jody
id=10, name=sky
结果说明:该示例中的栈是通过双向链表实现的,并且能存储任意类型的数据。示例中是以结构体类型的数据进行演示的,由于代码中已经给出了详细的注释,这里就不再介绍了。
栈的C++实现
C++的STL中本身就包含了stack类,基本上该stack类就能满足我们的需求,所以很少需要我们自己来实现。本部分介绍2种C++实现。
1. C++实现一:数组实现的栈,能存储任意类型的数据。
2. C++实现二:C++的 STL 中自带的"栈"(stack)的示例。
1. C++实现一:数组实现的栈,能存储任意类型的数据
实现代码
栈的实现文件(ArrayStack.h)
1 #ifndef ARRAY_STACK_HXX
2 #define ARRAY_STACK_HXX
3
4 #include <iostream>
5 #include "ArrayStack.h"
6 using namespace std;
7
8 template<class T> class ArrayStack{
9 public:
10 ArrayStack();
11 ~ArrayStack();
12
13 void push(T t);
14 T peek();
15 T pop();
16 int size();
17 int isEmpty();
18 private:
19 T *arr;
20 int count;
21 };
22
23 // 创建“栈”,默认大小是12
24 template<class T>
25 ArrayStack<T>::ArrayStack()
26 {
27 arr = new T[12];
28 if (!arr)
29 {
30 cout<<"arr malloc error!"<<endl;
31 }
32 }
33
34 // 销毁“栈”
35 template<class T>
36 ArrayStack<T>::~ArrayStack()
37 {
38 if (arr)
39 {
40 delete[] arr;
41 arr = NULL;
42 }
43 }
44
45 // 将val添加到栈中
46 template<class T>
47 void ArrayStack<T>::push(T t)
48 {
49 //arr[count++] = val;
50 arr[count++] = t;
51 }
52
53 // 返回“栈顶元素值”
54 template<class T>
55 T ArrayStack<T>::peek()
56 {
57 return arr[count-1];
58 }
59
60 // 返回“栈顶元素值”,并删除“栈顶元素”
61 template<class T>
62 T ArrayStack<T>::pop()
63 {
64 int ret = arr[count-1];
65 count--;
66 return ret;
67 }
68
69 // 返回“栈”的大小
70 template<class T>
71 int ArrayStack<T>::size()
72 {
73 return count;
74 }
75
76 // 返回“栈”是否为空
77 template<class T>
78 int ArrayStack<T>::isEmpty()
79 {
80 return size()==0;
81 }
82
83 #endif
栈的测试程序(Main.cpp)
1 #include <iostream>
2 #include "ArrayStack.h"
3 using namespace std;
4
5 int main()
6 {
7 int tmp=0;
8 ArrayStack<int> *astack = new ArrayStack<int>();
9
10 cout<<"main"<<endl;
11
12 // 将10, 20, 30 依次推入栈中
13 astack->push(10);
14 astack->push(20);
15 astack->push(30);
16
17 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
18 tmp = astack->pop();
19 cout<<"tmp="<<tmp<<endl;
20
21 // 只将“栈顶”赋值给tmp,不删除该元素.
22 tmp = astack->peek();
23
24 astack->push(40);
25
26 while (!astack->isEmpty())
27 {
28 tmp = astack->pop();
29 cout<<tmp<<endl;
30 }
31
32 return 0;
33 }
运行结果:
main
tmp=30
40
20
10
结果说明:关于"栈的声明和实现都在头文件中"的原因,是因为栈的实现利用了C++模板,而"C++编译器不能支持对模板的分离式编译"。这在"数据结构和算法01之 线性表"中已经介绍过了。 程序的实现和逻辑都非常简单。需要说明的是,采用C++模板实现的;但是,默认数组的大小只有12,而且该实现不支持动态扩展。
2. C++实现二:C++的 STL 中自带的"栈"(stack)的示例
实现代码(StlStack.cpp)
1 #include <iostream>
2 #include <stack>
3 using namespace std;
4
5 /**
6 * C++ 语言: STL 自带的“栈”(stack)的示例。
7 *
8 * @author skywang
9 * @date 2013/11/07
10 */
11 int main ()
12 {
13 int tmp=0;
14 stack<int> istack;
15
16 // 将10, 20, 30 依次推入栈中
17 istack.push(10);
18 istack.push(20);
19 istack.push(30);
20
21 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
22 istack.pop();
23
24 // 只将“栈顶”赋值给tmp,不删除该元素.
25 tmp = istack.top();
26
27 istack.push(40);
28
29 while (!istack.empty())
30 {
31 tmp = istack.top();
32 istack.pop();
33 cout<<tmp<<endl;
34 }
35
36 return 0;
37 }
运行结果:
40
20
10
栈的Java实现
和C++一样,JDK包中也提供了"栈"的实现,它就是集合框架中的Stack类。关于Stack类的原理,在"Java 集合系列07之 Stack详细介绍(源码解析)和使用示例"中,已经详细介绍过了。本部分给出2种Java实现
Java实现一:数组实现的栈,能存储任意类型的数据。
Java实现二:Java的 Collection集合 中自带的"栈"(stack)的示例。
1. Java实现一:数组实现的栈,能存储任意类型的数据
实现代码(GeneralArrayStack.java)
1 /**
2 * Java : 数组实现的栈,能存储任意类型的数据
3 *
4 * @author skywang
5 * @date 2013/11/07
6 */
7 import java.lang.reflect.Array;
8
9 public class GeneralArrayStack<T> {
10
11 private static final int DEFAULT_SIZE = 12;
12 private T[] mArray;
13 private int count;
14
15 public GeneralArrayStack(Class<T> type) {
16 this(type, DEFAULT_SIZE);
17 }
18
19 public GeneralArrayStack(Class<T> type, int size) {
20 // 不能直接使用mArray = new T[DEFAULT_SIZE];
21 mArray = (T[]) Array.newInstance(type, size);
22 count = 0;
23 }
24
25 // 将val添加到栈中
26 public void push(T val) {
27 mArray[count++] = val;
28 }
29
30 // 返回“栈顶元素值”
31 public T peek() {
32 return mArray[count-1];
33 }
34
35 // 返回“栈顶元素值”,并删除“栈顶元素”
36 public T pop() {
37 T ret = mArray[count-1];
38 count--;
39 return ret;
40 }
41
42 // 返回“栈”的大小
43 public int size() {
44 return count;
45 }
46
47 // 返回“栈”是否为空
48 public boolean isEmpty() {
49 return size()==0;
50 }
51
52 // 打印“栈”
53 public void PrintArrayStack() {
54 if (isEmpty()) {
55 System.out.printf("stack is Empty
");
56 }
57
58 System.out.printf("stack size()=%d
", size());
59
60 int i=size()-1;
61 while (i>=0) {
62 System.out.println(mArray[i]);
63 i--;
64 }
65 }
66
67 public static void main(String[] args) {
68 String tmp;
69 GeneralArrayStack<String> astack = new GeneralArrayStack<String>(String.class);
70
71 // 将10, 20, 30 依次推入栈中
72 astack.push("10");
73 astack.push("20");
74 astack.push("30");
75
76 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
77 tmp = astack.pop();
78 System.out.println("tmp="+tmp);
79
80 // 只将“栈顶”赋值给tmp,不删除该元素.
81 tmp = astack.peek();
82 System.out.println("tmp="+tmp);
83
84 astack.push("40");
85 astack.PrintArrayStack(); // 打印栈
86 }
87 }
运行结果:
1 tmp=30
2 tmp=20
3 stack size()=3
4 40
5 20
6 10
结果说明:GeneralArrayStack是通过数组实现的栈,而且GeneralArrayStack中使用到了泛型。
2. Java实现二:Java的 Collection集合 中自带的"栈"(stack)的示例
实现代码(StackTest.java)
1 import java.util.Stack;
2
3 /**
4 * Java : java集合包中的Stack的演示程序
5 *
6 * @author skywang
7 * @date 2013/11/07
8 */
9 public class StackTest {
10
11 public static void main(String[] args) {
12 int tmp=0;
13 Stack<Integer> astack = new Stack<Integer>();
14
15 // 将10, 20, 30 依次推入栈中
16 astack.push(10);
17 astack.push(20);
18 astack.push(30);
19
20 // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
21 tmp = astack.pop();
22 //System.out.printf("tmp=%d
", tmp);
23
24 // 只将“栈顶”赋值给tmp,不删除该元素.
25 tmp = (int)astack.peek();
26 //System.out.printf("tmp=%d
", tmp);
27
28 astack.push(40);
29 while(!astack.empty()) {
30 tmp = (int)astack.pop();
31 System.out.printf("tmp=%d
", tmp);
32 }
33 }
34 }
运行结果:
tmp=40
tmp=20
tmp=10