栈的图文解析 和 对应3种语言的实现(C/C++/Java)【转】
概要
本章会先对栈的原理进行介绍,然后分别通过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\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 }

运行结果:
- tmp=30
- tmp=20
- stack size()=3
- 40
- 20
结果说明:该示例中的栈,是通过"数组"来实现的!
由于代码中已经给出了详细了注释,这里就不再对函数进行说明了。仅对主函数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\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 }

代码说明:"运行结果" 以及 "主函数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!\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 }

双向链表的测试程序(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\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 }

代码说明:"运行结果" 以及 "主函数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!\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 }

双向链表的测试程序(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\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 }

运行结果:
- 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
结果说明:关于"栈的声明和实现都在头文件中"的原因,是因为栈的实现利用了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
栈的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\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 }

运行结果:
- 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\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 }

运行结果:
- tmp=40
- tmp=20
- tmp=10
栈的图文解析 和 对应3种语言的实现(C/C++/Java)【转】的更多相关文章
- 栈的图文解析 和 对应3种语言的实现(C/C++/Java)
概要 本章会先对栈的原理进行介绍,然后分别通过C/C++/Java三种语言来演示栈的实现示例.注意:本文所说的栈是数据结构中的栈,而不是内存模型中栈.内容包括:1. 栈的介绍2. 栈的C实现3. 栈的 ...
- 队列的图文解析 和 对应3种语言的实现(C/C++/Java)
概要 本章和介绍"栈"时的流程一样,先对队列进行介绍,然后分别给出队列的C.C++和Java三种语言的实现.内容包括:1. 队列的介绍2. 队列的C实现3. 队列的C++实现4. ...
- 选择排序的3种语言实现方法(C java python)
1.选择排序的思路是:遍历数组,第一遍找出所有成员的最小值,放到数组下标为0的位置,第二遍从剩余内容中,再次找出最小值,放到数组下标为1的位置,以此类推,遍历完成所有的数组内容,最后结果就是:数组是按 ...
- 数据结构图文解析之:栈的简介及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:队列详解与C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:AVL树详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 数据结构图文解析之:二叉堆详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
随机推荐
- Python3: 对两个字符串进行匹配
Python里一共有三种字符串匹配方式,用于判断一个字符串是否包含另一个字符串.比如判断字符串“HelloWorld”中是否包含“World”: def stringCompare(str1, str ...
- 常用操作提高效率 之 for 与in
问题如何而来: 对于刚参加工作的我 批量删除数据通常采用的是前端传递到后台一个对象的id字符串 通过逗号分隔的多个id 或者收的直接是一个id数组 两个原理一样第一个后台要在次使用split(& ...
- Github上的1000多本免费电子书重磅来袭!
Github上的1000多本免费电子书重磅来袭! 以前 StackOverFlow 也给出了一个免费电子书列表,现在在Github上可以看到时刻保持更新的列表了. 瞥一眼下面的书籍分类目录,你就能 ...
- 26、js阶段性复习
1.一元运算符 Operator + 可用于将变量转换为数字: <!DOCTYPE html> <html> <body> <p> typeof 操作符 ...
- 30分钟快速搭建Web CRUD的管理平台--django神奇魔法
加上你的准备的时间,估计30分钟完全够用了,因为最近在做爬虫管理平台,想着快速开发,没想到python web平台下有这么非常方便的框架,简洁而优雅.将自己的一些坑总结出来,方便给大家的使用. 准备环 ...
- Selenium八大元素定位方式
1.根据id来定位: import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.sele ...
- 功能规格说明书Version2
此功能规格说明书是Week8 功能规格说明书的第二个版本, 版本1地址:http://www.cnblogs.com/Z-XML/p/3407687.html 此功能规格说明书是面向用户的,所以作者将 ...
- gdb coredum 信息例子
http://blog.csdn.net/hzhsan/article/details/38227647
- shell 中的expect 用法
expect一般用于实现用脚本来自动远程登录,对远程机器执行相关操作 测试机上的expect目录一般在/usr/bin/expect路径 下面是从网上查询的用法总结: 1. expect中的判断语句: ...
- windows下自己常用的几个bat
1.samba映射盘符和解除 net use Z: "\\sambaserver ip\dir" "password" /user:"username ...