数据结构_栈(基于顺序表和链表)

栈是一种特殊的线性表,只允许在固定的一端进行插入删除元素操作,操作元素的一端称为栈顶,另一端称为栈底。不含任何元素的栈称为空栈,栈具有后进先出的特点,栈也可以称为后进先出的线性表。

那有了线性表链表为什么还要有栈,栈的操作相比较于顺序表、链表来说操作比较简单,出栈、入栈、取栈顶元素,更简单的操作就限制了操作的权利,也就减少了出现错误的机会,在栈能满足的情况下,就不需要使用顺序表或者链表。


以下实现基于顺序表和链表实现栈的简单操作:

一、顺序表实现:
     顺序表用数组来实现,数组是定长的,可以进行扩容,使用顺序表来模拟实现栈,对顺序表尾插实现入栈,尾删实现出栈。以下为代码实现:
// 头文件及结构体声明
  1 #pragma once                                                                                                                      
  2                                                                                                                                   
  3 #include <stdio.h>                                                                                                                
  4 #include <stddef.h>                                                                                                               
  5 #include <stdlib.h>                                                                                                               
  6 #include <string.h>                                                                                                               
  7                                                                                                                                   
  8 typedef char SeqStackType;                                                                                                        
  9                                                                                                                                   
10 typedef struct SeqStack {                                                                                                         
11     SeqStackType* data;         // 指向开辟内存空间,用于扩容                                                                                                  
12     size_t size;                 //  有效元素个数                                                                                                 
13     size_t capacity;         //  data 指向的空间容纳的最大个数,size超过 capacity时进行扩容                                                                                                     
14 }SeqStack;
 
1.初始化栈
    3 void SeqStackInit(SeqStack* stack)                                                                                              
    4 {                                                                                                                               
    5     if(stack == NULL){                                                                                                          
    6         // 非法输入                                                                                                             
    7         return;                                                                                                                 
    8     }                                                                                                                           
    9     stack->size = 0;                                                                                                            
   10    stack->capacity = 1024;                                                                                                     
   11    stack->data = (SeqStackType*)malloc(stack->capacity * sizeof(SeqStackType));   //  申请初始内存空间                                             
   12    return;                                                                                                                     
   13 }  

2.销毁栈
   15 void SeqStackDestroy(SeqStack* stack)                                                                                           
   16 {                                                                                                                               
   17     if(stack == NULL){                                                                                                          
   18         return;                                                                                                                 
   19     }                                                                                                                           
   20     free(stack->data);                                                                                                          
   21     stack->data = NULL;                                                                                                         
   22     stack->size = 0;                                                                                                            
   23     stack->capacity = 0;                                                                                                        
   24     return;                                                                                                                     
   25 }

3.元素入栈
//  重置栈大小(扩容)
   27 void SeqStackResize(SeqStack* stack)                                                                                            
   28 {                                                                                                                               
   29     if(stack == NULL){                                                                                                          
   30         return;                                                                                                                 
   31     }                                                                                                                           
   32     if(stack->size < stack->capacity){                                                                                          
   33         return;                                                                                                                 
   34     }                                                                                                                           
   35     stack->capacity = stack->capacity * 2 + 1;   // 改变扩大范围                                                            
   36     SeqStackType* new = (SeqStackType*)malloc(stack->capacity * sizeof(SeqStackType));                                          
   37     size_t i = 0;                                                                                                               
   38     for(; i < stack->size; i++){     // 将原内存的数据搬运到新的内存空间                                                                                           
   39         new[i] = stack->data[i];                                                                                                
   40     }                                                                                                                           
   41     free(stack->data);                                                                                                          
   42     stack->data = new;       // 更新地址                                                                                                   
   43     return;                                                                                                                     
   44 }

//  入栈
   46 void SeqStackPush(SeqStack* stack, SeqStackType value)                                                                          
   47 {                                                                                                                               
   48     if(stack == NULL){                                                                                                          
   49         return;                                                                                                                 
   50     }                                                                                                                           
   51     if(stack->size >= stack->capacity){                                                                                         
   52         // 栈已满,扩容                                                                                                         
   53         SeqStackResize(stack);                                                                                                  
   54     }                                                                                                                           
   55     stack->data[stack->size++] = value;                                                                                         
   56     return;                                                                                                                     
   57 }

4.元素出栈
   59 void SeqStackPop(SeqStack* stack)                                                                                               
   60 {                                                                                                                               
   61     if(stack == NULL){                                                                                                          
   62         return;                                                                                                                 
   63     }                                                                                                                           
   64     if(stack->size == 0)                                                                                                        
   65     {                                                                                                                           
   66         // 空栈                                                                                                                 
   67         return;                                                                                                                 
   68     }                                                                                                                           
   69     stack->size--;          // 出栈减有效元素                                                                                                    
   70     return;                                                                                                                     
   71 }

5.取栈顶元素
   73 int SeqStackTop(SeqStack* stack, SeqStackType* value)                                                                           
   74 {                                                                                                                               
   75     if(stack == NULL || value == NULL){                                                                                         
   76         return 0;                                                                                                               
   77     }                                                                                                                           
   78     if(stack->size == 0){                                                                                                       
   79         // 空栈                                                                                                                 
   80         return 0;                                                                                                               
   81     }                                                                                                                           
   82     *value = stack->data[stack->size - 1];            // 返回栈顶元素,有效元素个数减小                                                                          
   83     return 1;                                                                                                                   
   84 }

6.打印函数
   96 void SeqStackPrint(const SeqStackType* msg, SeqStack* stack)                                                                    
   97 {                                                                                                                               
   98     if(stack == NULL || msg == NULL){                                                                                           
   99         return;                                                                                                                 
  100     }                                                                                                                           
  101     printf("%s\n", msg);                                                                                                        
  102     size_t i = 0;                                                                                                               
  103     for(; i < stack->size; i++){                                                                                                
  104         printf("[%c]  ", stack->data[i]);                                                                                       
  105     }                                                                                                                           
  106     printf("\n");                                                                                                               
  107 }

二、链表实现:
    基于链表实现栈,使用带头结点链表操作方便,入栈新的元素申请空间,出栈释放元素,链表的尾部需要遍历或者保存起来,比较麻烦,可以采用头插头删来实现入栈出栈,以下为代码实现:
// 头文件及结构体声明
  1 #pragma once                                                                                                                      
  2                                                                                                                                   
  3 #include<stdio.h>                                                                                                                 
  4 #include<stdlib.h>                                                                                                                
  5 #include<string.h>                                                                                                                
  6 #include<stddef.h>                                                                                                                
  7                                                                                                                                   
  8 typedef char LinkStackType;                                                                                                       
  9                                                                                                                                   
10 typedef struct LinkStack{                                                                                                         
11     LinkStackType data;                                                                                                           
12     struct LinkStack* next;                                                                                                       
13 }LinkStack;  

1.初始化、销毁栈
// 初始化
  3 void LinkStackInit(LinkStack** head)                                                                                              
  4 {                                                                                                                                 
  5     if(head == NULL){                                                                                                             
  6         // 非法输入                                                                                                               
  7         return;                                                                                                                   
  8     }                                                                                                                             
  9     *head = (LinkStack*)malloc(sizeof(LinkStack));                                                                                
10     (*head)->data = 0;                                                                                                            
11     (*head)->next = NULL;                                                                                                        
12     return;                                                                                                                       
13 }                                                                                                                                 

// 销毁栈                                                                                                                             
15 void LinkStackDestory(LinkStack** head)                                                                                           
16 {                                                                                                                                 
17     if(head == NULL){          
18         return;                                                                                                                   
19     }                                                                                                                                                                                                                                
20     free(*head);                                                                                                                  
21     *head = NULL;                                                                                                                 
22     return;                                                                                                                       
23 }

2.入栈元素
// 创建结点
25 LinkStack* LinkStackCreateNode(LinkStackType value)                                                                               
26 {                                                                                                                                 
27     LinkStack* new_node = (LinkStack*)malloc(sizeof(LinkStack));                                                                  
28     new_node->data = value;                                                                                                       
29     new_node->next = NULL;                                                                                                        
30     return new_node;                                                                                                              
31 }                                                                                                                                 

//  销毁结点                                                                                                                      
33 void LinkStackDestoryNode(LinkStack* pos)                                                                                         
34 {                                                                                                                                 
35     if(pos){                                                                                                                      
36         free(pos);                                                                                                                
37     }                                                                                                                             
38     pos = NULL;                                                                                                                   
39     return;                                                                                                                       
40 }

//  入栈
42 void LinkStackPush(LinkStack* head, LinkStackType value)                                                                          
43 {                                                                                                                                 
44     if(head == NULL){                                                                                                             
45         return;                                                                                                                   
46     }                                                                                                                             
47     LinkStack* new_node = LinkStackCreateNode(value);                                                                             
48     if(head->next == NULL){                                                                                                       
49         // 空链表                                                                                                                 
50         head->next = new_node;                                                                                                    
51         return;                                                                                                                   
52     }                                                                                                                             
53     LinkStack* tmp = head->next;       // 保存要删除结点后边的结点                                                                                           
54     head->next = new_node;                                                                                                        
55     new_node->next = tmp;                                                                                                         
56     return;                                                                                                                       
57 }

3.出栈元素
59 void LinkStackPop(LinkStack* head)                                                                                                
60 {                                                                                                                                 
61     if(head == NULL){                                                                                                             
62         // 非法输入                                                                                                               
63         return;                                                                                                                   
64     }                                                                                                                             
65     if(head->next == NULL){                                                                                                       
66         printf("空栈.\n");                                                                                                        
67         return;                                                                                                                   
68     }                                                                                                                             
69     LinkStack* tmp = head->next;                                                                                                  
70     head->next = tmp->next;                                                                                                       
71     LinkStackDestoryNode(tmp);                                                                                                    
72     return;                                                                                                                       
73 }   



4.取栈顶元素
75 int LinkStackTop(LinkStack* head, LinkStackType* top)                                                                             
76 {                                                                                                                                 
77     if(head == NULL || top == NULL){                                                                                              
78         return 0;                                                                                                                 
79     }                                                                                                                             
80     if(head->next == NULL){                                                                                                       
81         return 0;                                                                                                                 
82     }                                                                                                                             
83     *top = head->next->data;                                                                                                      
84     return 1;                                                                                                                     
85 }

5.打印函数
93 void LinkStackPrint(const LinkStackType* msg, LinkStack* head)                                                                    
94 {                                                                                                                                 
95     if(msg ==NULL || head ==NULL){                                                                                                
96         // 非法输入                                                                                                               
97         return;                                                                                                                   
98     }                                                                                                                             
99     printf("%s\n", msg);                                                                                                          
100     LinkStack* cur = head->next;                                                                                                  
101     while(cur != NULL){                                                                                                           
102         printf("[%c] ", cur->data);                                                                                               
103         cur = cur->next;                                                                                                          
104     }                                                                                                                             
105     printf("\n");                                                                                                                 
106 }

二、顺序表、链表实现栈的差异
    顺序表栈:出栈、取栈顶元素时间复杂度为 O(1),入栈的时间复杂度为O(n),扩容需要搬运元素,但是代码简单,直接对有效元素个数进行更改;
    链表栈:入栈、出栈、取栈顶元素时间复杂度为 O(1) ,每次插入新元素需要单独申请空间,对元素的基本操作,需要改变指针,代码比顺序栈麻烦一点。
   

猜你喜欢

转载自blog.csdn.net/Cherubim1/article/details/80233752