• 栈的图文解析 和 对应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
    ");
     79         return ;
     80     }
     81 
     82     printf("stack size()=%d
    ", size());
     83 
     84     int i=size()-1;
     85     while (i>=0)
     86     {
     87         printf("%d
    ", arr[i]);
     88         i--;
     89     }
     90 }
     91 
     92 
     93 void main() 
     94 {
     95     int tmp=0;
     96 
     97     // 创建“栈”
     98     create_array_stack(12);
     99 
    100     // 将10, 20, 30 依次推入栈中
    101     push(10);
    102     push(20);
    103     push(30);
    104 
    105     //print_array_stack();    // 打印栈
    106 
    107     // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
    108     tmp = pop();
    109     printf("tmp=%d
    ", tmp);
    110     //print_array_stack();    // 打印栈
    111 
    112     // 只将“栈顶”赋值给tmp,不删除该元素.
    113     tmp = peek();
    114     printf("tmp=%d
    ", tmp);
    115     //print_array_stack();    // 打印栈
    116 
    117     push(40);
    118     print_array_stack();    // 打印栈
    119 
    120     // 销毁栈
    121     destroy_array_stack();
    122 }
    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
    ");
    114         return 0;
    115     }
    116 
    117     printf("stack size()=%d
    ", size());
    118 
    119     struct node *pnode=NULL;
    120 
    121     while (phead != NULL) {
    122         printf("%d
    ", phead->val);
    123         pnode = phead;
    124         phead = phead->next;
    125         free(pnode);
    126     }
    127 }
    128 
    129 void main() 
    130 {
    131     int tmp=0;
    132 
    133     // 将10, 20, 30 依次推入栈中
    134     push(10);
    135     push(20);
    136     push(30);
    137 
    138     //print_single_link();    // 打印栈
    139 
    140     // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
    141     tmp = pop();
    142     printf("tmp=%d
    ", tmp);
    143     //print_single_link();    // 打印栈
    144 
    145     // 只将“栈顶”赋值给tmp,不删除该元素.
    146     tmp = peek();
    147     printf("tmp=%d
    ", tmp);
    148     //print_single_link();    // 打印栈
    149 
    150     push(40);
    151     print_single_link();    // 打印栈
    152 
    153     // 销毁栈
    154     destroy_single_link();
    155 }
    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!
    ");
     31         return NULL;
     32     }
     33     // 默认的,pnode的前一节点和后一节点都指向它自身
     34     pnode->prev = pnode->next = pnode;
     35     // 节点的值为value
     36     pnode->value = value;
     37 
     38     return pnode;
     39 }
     40 
     41 // 新建“双向链表”。成功,返回0;否则,返回-1。
     42 int create_dlink()
     43 {
     44     // 创建表头
     45     phead = create_node(-1);
     46     if (!phead)
     47         return -1;
     48 
     49     // 设置“节点个数”为0
     50     count = 0;
     51 
     52     return 0;
     53 }
     54 
     55 // “双向链表是否为空”
     56 int dlink_is_empty()
     57 {
     58     return count == 0;
     59 }
     60 
     61 // 返回“双向链表的大小”
     62 int dlink_size() {
     63     return count;
     64 }
     65 
     66 // 获取“双向链表中第index位置的节点”
     67 static node* get_node(int index) 
     68 {
     69     if (index<0 || index>=count)
     70     {
     71         printf("%s failed! the index in out of bound!
    ", __func__);
     72         return NULL;
     73     }
     74 
     75     // 正向查找
     76     if (index <= (count/2))
     77     {
     78         int i=0;
     79         node *pnode=phead->next;
     80         while ((i++) < index) 
     81             pnode = pnode->next;
     82 
     83 //        printf("%s %d i=%d, pnode->value=%d
    ", 
     84 //                __func__, __LINE__, i, pnode->value);
     85         return pnode;
     86     }
     87 
     88     // 反向查找
     89     int j=0;
     90     int rindex = count - index - 1;
     91     node *rnode=phead->prev;
     92     while ((j++) < rindex) 
     93         rnode = rnode->prev;
     94 
     95 //    printf("%s %d j=%d, rnode->value=%d
    ", 
     96 //            __func__, __LINE__, j, rnode->value);
     97     return rnode;
     98 }
     99 
    100 // 获取“第一个节点”
    101 static node* get_first_node() 
    102 {
    103     return get_node(0);
    104 }
    105 
    106 // 获取“最后一个节点”
    107 static node* get_last_node() 
    108 {
    109     return get_node(count-1);
    110 }
    111 
    112 // 获取“双向链表中第index位置的元素的值”。成功,返回节点值;否则,返回-1。
    113 int dlink_get(int index)
    114 {
    115     node *pindex=get_node(index);
    116     if (!pindex) 
    117     {
    118         printf("%s failed!
    ", __func__);
    119         return -1;
    120     }
    121 
    122     return pindex->value;
    123 
    124 }
    125 
    126 // 获取“双向链表中第1个元素的值”
    127 int dlink_get_first()
    128 {
    129     return dlink_get(0);
    130 }
    131 
    132 // 获取“双向链表中最后1个元素的值”
    133 int dlink_get_last()
    134 {
    135     return dlink_get(count-1);
    136 }
    137 
    138 // 将“value”插入到index位置。成功,返回0;否则,返回-1。
    139 int dlink_insert(int index, int value) 
    140 {
    141     // 插入表头
    142     if (index==0)
    143         return dlink_insert_first(value);
    144 
    145     // 获取要插入的位置对应的节点
    146     node *pindex=get_node(index);
    147     if (!pindex) 
    148         return -1;
    149 
    150     // 创建“节点”
    151     node *pnode=create_node(value);
    152     if (!pnode)
    153         return -1;
    154 
    155     pnode->prev = pindex->prev;
    156     pnode->next = pindex;
    157     pindex->prev->next = pnode;
    158     pindex->prev = pnode;
    159     // 节点个数+1
    160     count++;
    161 
    162     return 0;
    163 }
    164 
    165 // 将“value”插入到表头位置
    166 int dlink_insert_first(int value) 
    167 {
    168     node *pnode=create_node(value);
    169     if (!pnode)
    170         return -1;
    171 
    172     pnode->prev = phead;
    173     pnode->next = phead->next;
    174     phead->next->prev = pnode;
    175     phead->next = pnode;
    176     count++;
    177     return 0;
    178 }
    179 
    180 // 将“value”插入到末尾位置
    181 int dlink_append_last(int value) 
    182 {
    183     node *pnode=create_node(value);
    184     if (!pnode)
    185         return -1;
    186     
    187     pnode->next = phead;
    188     pnode->prev = phead->prev;
    189     phead->prev->next = pnode;
    190     phead->prev = pnode;
    191     count++;
    192     return 0;
    193 }
    194 
    195 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
    196 int dlink_delete(int index)
    197 {
    198     node *pindex=get_node(index);
    199     if (!pindex) 
    200     {
    201         printf("%s failed! the index in out of bound!
    ", __func__);
    202         return -1;
    203     }
    204 
    205     pindex->next->prev = pindex->prev;
    206     pindex->prev->next = pindex->next;
    207     free(pindex);
    208     count--;
    209 
    210     return 0;
    211 }    
    212 
    213 // 删除第一个节点
    214 int dlink_delete_first() 
    215 {
    216     return dlink_delete(0);
    217 }
    218 
    219 // 删除组后一个节点
    220 int dlink_delete_last() 
    221 {
    222     return dlink_delete(count-1);
    223 }
    224 
    225 // 撤销“双向链表”。成功,返回0;否则,返回-1。
    226 int destroy_dlink()
    227 {
    228     if (!phead)
    229     {
    230         printf("%s failed! dlink is null!
    ", __func__);
    231         return -1;
    232     }
    233 
    234     node *pnode=phead->next;
    235     node *ptmp=NULL;
    236     while(pnode != phead)
    237     {
    238         ptmp = pnode;
    239         pnode = pnode->next;
    240         free(ptmp);
    241     }
    242 
    243     free(phead);
    244     phead = NULL;
    245     count = 0;
    246 
    247     return 0;
    248 }
    249 
    250 // 打印“双向链表”
    251 void print_dlink()
    252 {
    253     if (count==0 || (!phead))
    254     {
    255         printf("stack is Empty
    ");
    256         return ;
    257     }
    258 
    259     printf("stack size()=%d
    ", count);
    260     node *pnode=phead->next;
    261     while(pnode != phead)
    262     {
    263         printf("%d
    ", pnode->value);
    264         pnode = pnode->next;
    265     }
    266 }
    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
    ", tmp);
    77     //print_dlink_stack();    // 打印栈
    78 
    79     // 只将“栈顶”赋值给tmp,不删除该元素.
    80     tmp = peek();
    81     printf("tmp=%d
    ", tmp);
    82     //print_dlink_stack();    // 打印栈
    83 
    84     push(40);
    85     print_dlink_stack();    // 打印栈
    86 
    87     // 销毁栈
    88     destroy_dlink_stack();
    89 }
    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!
    ");
     32         return NULL;
     33     }
     34     // 默认的,pnode的前一节点和后一节点都指向它自身
     35     pnode->prev = pnode->next = pnode;
     36     // 节点的值为pval
     37     pnode->p = pval;
     38 
     39     return pnode;
     40 }
     41 
     42 // 新建“双向链表”。成功,返回0;否则,返回-1。
     43 int create_dlink()
     44 {
     45     // 创建表头
     46     phead = create_node(NULL);
     47     if (!phead)
     48         return -1;
     49 
     50     // 设置“节点个数”为0
     51     count = 0;
     52 
     53     return 0;
     54 }
     55 
     56 // “双向链表是否为空”
     57 int dlink_is_empty()
     58 {
     59     return count == 0;
     60 }
     61 
     62 // 返回“双向链表的大小”
     63 int dlink_size() {
     64     return count;
     65 }
     66 
     67 // 获取“双向链表中第index位置的节点”
     68 static node* get_node(int index) 
     69 {
     70     if (index<0 || index>=count)
     71     {
     72         printf("%s failed! index out of bound!
    ", __func__);
     73         return NULL;
     74     }
     75 
     76     // 正向查找
     77     if (index <= (count/2))
     78     {
     79         int i=0;
     80         node *pnode=phead->next;
     81         while ((i++) < index) 
     82             pnode = pnode->next;
     83 
     84         return pnode;
     85     }
     86 
     87     // 反向查找
     88     int j=0;
     89     int rindex = count - index - 1;
     90     node *rnode=phead->prev;
     91     while ((j++) < rindex) 
     92         rnode = rnode->prev;
     93 
     94     return rnode;
     95 }
     96 
     97 // 获取“第一个节点”
     98 static node* get_first_node() 
     99 {
    100     return get_node(0);
    101 }
    102 
    103 // 获取“最后一个节点”
    104 static node* get_last_node() 
    105 {
    106     return get_node(count-1);
    107 }
    108 
    109 // 获取“双向链表中第index位置的元素”。成功,返回节点值;否则,返回-1。
    110 void* dlink_get(int index)
    111 {
    112     node *pindex=get_node(index);
    113     if (!pindex) 
    114     {
    115         printf("%s failed!
    ", __func__);
    116         return NULL;
    117     }
    118 
    119     return pindex->p;
    120 
    121 }
    122 
    123 // 获取“双向链表中第1个元素的值”
    124 void* dlink_get_first()
    125 {
    126     return dlink_get(0);
    127 }
    128 
    129 // 获取“双向链表中最后1个元素的值”
    130 void* dlink_get_last()
    131 {
    132     return dlink_get(count-1);
    133 }
    134 
    135 // 将“pval”插入到index位置。成功,返回0;否则,返回-1。
    136 int dlink_insert(int index, void* pval) 
    137 {
    138     // 插入表头
    139     if (index==0)
    140         return dlink_insert_first(pval);
    141 
    142     // 获取要插入的位置对应的节点
    143     node *pindex=get_node(index);
    144     if (!pindex) 
    145         return -1;
    146 
    147     // 创建“节点”
    148     node *pnode=create_node(pval);
    149     if (!pnode)
    150         return -1;
    151 
    152     pnode->prev = pindex->prev;
    153     pnode->next = pindex;
    154     pindex->prev->next = pnode;
    155     pindex->prev = pnode;
    156     // 节点个数+1
    157     count++;
    158 
    159     return 0;
    160 }
    161 
    162 // 将“pval”插入到表头位置
    163 int dlink_insert_first(void *pval) 
    164 {
    165     node *pnode=create_node(pval);
    166     if (!pnode)
    167         return -1;
    168 
    169     pnode->prev = phead;
    170     pnode->next = phead->next;
    171     phead->next->prev = pnode;
    172     phead->next = pnode;
    173     count++;
    174     return 0;
    175 }
    176 
    177 // 将“pval”插入到末尾位置
    178 int dlink_append_last(void *pval) 
    179 {
    180     node *pnode=create_node(pval);
    181     if (!pnode)
    182         return -1;
    183     
    184     pnode->next = phead;
    185     pnode->prev = phead->prev;
    186     phead->prev->next = pnode;
    187     phead->prev = pnode;
    188     count++;
    189     return 0;
    190 }
    191 
    192 // 删除“双向链表中index位置的节点”。成功,返回0;否则,返回-1。
    193 int dlink_delete(int index)
    194 {
    195     node *pindex=get_node(index);
    196     if (!pindex) 
    197     {
    198         printf("%s failed! the index in out of bound!
    ", __func__);
    199         return -1;
    200     }
    201 
    202     pindex->next->prev = pindex->prev;
    203     pindex->prev->next = pindex->next;
    204     free(pindex);
    205     count--;
    206 
    207     return 0;
    208 }    
    209 
    210 // 删除第一个节点
    211 int dlink_delete_first() 
    212 {
    213     return dlink_delete(0);
    214 }
    215 
    216 // 删除组后一个节点
    217 int dlink_delete_last() 
    218 {
    219     return dlink_delete(count-1);
    220 }
    221 
    222 // 撤销“双向链表”。成功,返回0;否则,返回-1。
    223 int destroy_dlink()
    224 {
    225     if (!phead)
    226     {
    227         printf("%s failed! dlink is null!
    ", __func__);
    228         return -1;
    229     }
    230 
    231     node *pnode=phead->next;
    232     node *ptmp=NULL;
    233     while(pnode != phead)
    234     {
    235         ptmp = pnode;
    236         pnode = pnode->next;
    237         free(ptmp);
    238     }
    239 
    240     free(phead);
    241     phead = NULL;
    242     count = 0;
    243 
    244     return 0;
    245 }
    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
    ", 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
    ");
    56         }
    57 
    58         System.out.printf("stack size()=%d
    ", size());
    59 
    60         int i=size()-1;
    61         while (i>=0) {
    62             System.out.println(mArray[i]);
    63             i--;
    64         }
    65     }
    66 
    67     public static void main(String[] args) {
    68         String tmp;
    69         GeneralArrayStack<String> astack = new GeneralArrayStack<String>(String.class);
    70 
    71         // 将10, 20, 30 依次推入栈中
    72         astack.push("10");
    73         astack.push("20");
    74         astack.push("30");
    75 
    76         // 将“栈顶元素”赋值给tmp,并删除“栈顶元素”
    77         tmp = astack.pop();
    78         System.out.println("tmp="+tmp);
    79 
    80         // 只将“栈顶”赋值给tmp,不删除该元素.
    81         tmp = astack.peek();
    82         System.out.println("tmp="+tmp);
    83 
    84         astack.push("40");
    85         astack.PrintArrayStack();    // 打印栈
    86     }
    87 }
    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
    ", tmp);
    23 
    24         // 只将“栈顶”赋值给tmp,不删除该元素.
    25         tmp = (int)astack.peek();
    26         //System.out.printf("tmp=%d
    ", tmp);
    27 
    28         astack.push(40);
    29         while(!astack.empty()) {
    30             tmp = (int)astack.pop();
    31             System.out.printf("tmp=%d
    ", tmp);
    32         }
    33     }
    34 }
    View Code

    运行结果

    tmp=40
    tmp=20
    tmp=10

     

  • 相关阅读:
    easyui combobox 实现联动
    smartWizard 和 uploadify 插件
    easyui panel href 引用页面导致的命名冲突问题
    Installshield 多语言安装包 和 安装序列号验证,及如何解决 Failed to set code page for Language 46 问题
    easyui 之tab和portal 在IE9下使用iframe时报未定义错误的解决方法
    easyui datagrid 动态列和前端分页,以及加载Datatable
    easyui 动态创建模式对话框
    移动硬盘一个分区“数据循环冗余错误”要求格式化解决方法
    easyui 开发中的通用类库
    easyui datagrid 工具栏实现方式
  • 原文地址:https://www.cnblogs.com/skywang12345/p/3562239.html
Copyright © 2020-2023  润新知