栈的图文解析 和 对应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 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\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
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\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

转载于:https://www.cnblogs.com/chengjian-physique/p/10101429.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值