棧的圖文解析 和 對應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) 向棧中添加/刪除數據時,只能從棧頂進行操作。

棧通常包括的三種操作:pushpeekpop
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 }
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)

  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)

 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)

  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)

 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)

 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)

  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)

  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)

 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)

 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)

 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)

 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

運行結果

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)

 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM