栈的图文解析 和 对应3种语言的实现(C/C++/Java)

时间:2022-07-13 17:36:45

 

概要

本章会先对栈的原理进行介绍,然后分别通过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) 向栈中添加/删除数据时,只能从栈顶进行操作。

栈通常包括的三种操作:pushpeekpop
push -- 向栈中添加元素。
peek -- 返回栈顶元素。
pop  -- 返回并删除栈顶元素的操作。

 

1. 栈的示意图

栈的图文解析 和 对应3种语言的实现(C/C++/Java)

栈中的数据依次是 30 --> 20 --> 10

 

2. 出栈

栈的图文解析 和 对应3种语言的实现(C/C++/Java)

出栈前:栈顶元素是30。此时,栈中的元素依次是 30 --> 20 --> 10
出栈后:30出栈之后,栈顶元素变成20。此时,栈中的元素依次是 20 --> 10

 

3. 入栈

栈的图文解析 和 对应3种语言的实现(C/C++/Java)

入栈前:栈顶元素是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)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
  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\n");
 79         return ;
 80     }
 81 
 82     printf("stack size()=%d\n", size());
 83 
 84     int i=size()-1;
 85     while (i>=0)
 86     {
 87         printf("%d\n", 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\n", tmp);
110     //print_array_stack();    // 打印栈
111 
112     // 只将“栈顶”赋值给tmp,不删除该元素.
113     tmp = peek();
114     printf("tmp=%d\n", tmp);
115     //print_array_stack();    // 打印栈
116 
117     push(40);
118     print_array_stack();    // 打印栈
119 
120     // 销毁栈
121     destroy_array_stack();
122 }
View Code

运行结果

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)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
  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\n");
114         return 0;
115     }
116 
117     printf("stack size()=%d\n", size());
118 
119     struct node *pnode=NULL;
120 
121     while (phead != NULL) {
122         printf("%d\n", 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\n", tmp);
143     //print_single_link();    // 打印栈
144 
145     // 只将“栈顶”赋值给tmp,不删除该元素.
146     tmp = peek();
147     printf("tmp=%d\n", tmp);
148     //print_single_link();    // 打印栈
149 
150     push(40);
151     print_single_link();    // 打印栈
152 
153     // 销毁栈
154     destroy_single_link();
155 }
View Code

代码说明"运行结果" 以及 "主函数main的逻辑"都和"C语言实现一"的一样。不同的是,该示例中的栈是通过单向链表实现的。

 

3. C语言实现三:双向链表实现的栈,并且只能存储int数据

实现代码
双向链表的头文件(double_link.h)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
 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 
View Code

双向链表的实现文件double_link.c)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
  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!\n");
 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!\n", __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\n", 
 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\n", 
 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!\n", __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!\n", __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!\n", __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\n");
256         return ;
257     }
258 
259     printf("stack size()=%d\n", count);
260     node *pnode=phead->next;
261     while(pnode != phead)
262     {
263         printf("%d\n", pnode->value);
264         pnode = pnode->next;
265     }
266 }
View Code

双向链表的测试程序(dlink_stack.c)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
 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\n", tmp);
77     //print_dlink_stack();    // 打印栈
78 
79     // 只将“栈顶”赋值给tmp,不删除该元素.
80     tmp = peek();
81     printf("tmp=%d\n", tmp);
82     //print_dlink_stack();    // 打印栈
83 
84     push(40);
85     print_dlink_stack();    // 打印栈
86 
87     // 销毁栈
88     destroy_dlink_stack();
89 }
View Code

代码说明"运行结果" 以及 "主函数main的逻辑"都和前两个示例的一样。不同的是,该示例中的栈是通过双向链表实现的。

 

4. C语言实现四:双向链表实现的栈,能存储任意类型的数据

实现代码
双向链表的头文件(double_link.h)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
 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 
View Code

双向链表的实现文件(double_link.c)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
  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!\n");
 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!\n", __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!\n", __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!\n", __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!\n", __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 }
View Code

双向链表的测试程序(dlink_stack.c)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
  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\n", 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 }
View Code

运行结果

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)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
 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
View Code

栈的测试程序(Main.cpp)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
 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 }
View Code

运行结果

main
tmp=30
40
20
10

结果说明关于"栈的声明和实现都在头文件中"的原因,是因为栈的实现利用了C++模板,而"C++编译器不能支持对模板的分离式编译"。这在"数据结构和算法01之 线性表"中已经介绍过了。  程序的实现和逻辑都非常简单。需要说明的是,采用C++模板实现的;但是,默认数组的大小只有12,而且该实现不支持动态扩展。

 

2. C++实现二:C++的 STL 中自带的"栈"(stack)的示例

实现代码(StlStack.cpp)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
 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 }
View Code

运行结果

40
20
10

 

栈的Java实现

和C++一样,JDK包中也提供了"栈"的实现,它就是集合框架中的Stack类。关于Stack类的原理,在"Java 集合系列07之 Stack详细介绍(源码解析)和使用示例"中,已经详细介绍过了。本部分给出2种Java实现
Java实现一:数组实现的栈,能存储任意类型的数据。
Java实现二:Java的 Collection集合 中自带的"栈"(stack)的示例。

 

1. Java实现一:数组实现的栈,能存储任意类型的数据

实现代码(GeneralArrayStack.java)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/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\n");
56         }
57 
58         System.out.printf("stack size()=%d\n", 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 }
View Code

运行结果

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/Java)
1 tmp=30
2 tmp=20
3 stack size()=3
4 40
5 20
6 10
View Code

结果说明GeneralArrayStack是通过数组实现的栈,而且GeneralArrayStack中使用到了泛型。

 

2. Java实现二:Java的 Collection集合 中自带的"栈"(stack)的示例

实现代码(StackTest.java)

栈的图文解析 和 对应3种语言的实现(C/C++/Java)栈的图文解析 和 对应3种语言的实现(C/C++/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\n", tmp);
23 
24         // 只将“栈顶”赋值给tmp,不删除该元素.
25         tmp = (int)astack.peek();
26         //System.out.printf("tmp=%d\n", tmp);
27 
28         astack.push(40);
29         while(!astack.empty()) {
30             tmp = (int)astack.pop();
31             System.out.printf("tmp=%d\n", tmp);
32         }
33     }
34 }
View Code

运行结果

tmp=40
tmp=20
tmp=10