根据清华大学出版社《数据结构(C语言版)》第三章所述,栈是限定仅在表尾进行插入或删除操作的线性表(其本质还是一个线性表)。其特性是数据入口和出口都是同一个,因此遵循“先入后出”的特性。
既然是一个线性表,而且入口和出口相同,那么该结构需要有以下的数据属性:
1. 栈底指针(struct Stack*base),栈的存储首地址。
2. 栈顶指针(struct Stack *top),可以看成是一个游标,该指针所指向的位置始终指向栈中最新存入数据的下一位(前提是*base存储的是栈的首个元素)。
3. 栈的大小(ElemType size), 表示栈的深度,一般为一个常量。
----------------------------------------------------------------------------------------------------
栈作为特殊的线性表,继承了线性表的部分操作。
1. 构建栈(InitStack)。
2. 销毁栈 (DestroyStack)。
3. 插入数据(Push)。
4. 弹出数据(Pop)。
5. 清空栈 (ClearStack)。
6. 获取栈顶元素(GetTop)。
还有辅助操作:
----------------------------------------------------------------------------------------------------
7. 栈是否为空(IsEmpty)。
8. 栈是否已满(IsFull)。
具体实现如下:
1 #include <iostream> 2 using namespace std; 3 4 #define STACK_SIZE 100 5 struct Stack 6 { 7 int *top; 8 int *base; 9 int size; 10 }Stack; 11 12 /*********************************** 13 * Function Statements 14 ***********************************/ 15 bool InitStack(struct Stack &S); 16 bool IsEmpty(struct Stack &S); 17 bool IsFull(struct Stack &S); 18 void Push(struct Stack &S, int e); 19 void Pop(struct Stack &S, int &e); 20 bool DestroyStack(struct Stack &S); 21 bool ClearStack(struct Stack &S); 22 void printStack(struct Stack &S); 23 24 25 int main() 26 { 27 struct Stack S; 28 int b,n; 29 if(InitStack(S)==false) 30 { 31 cout<<"Init Stack error!"<<endl; 32 exit(0); 33 } 34 cout<<"push a data into stack:"<<endl; 35 36 n=8; 37 38 //压栈 39 cout<<"压栈操作"<<endl; 40 while(n--) 41 { 42 Push(S,n); 43 printStack(S); 44 } 45 46 //弹栈 47 cout<<"弹栈操作"<<endl; 48 while(n<4) 49 { 50 Pop(S,b); 51 printStack(S); 52 n++; 53 } 54 55 // 清栈 56 cout<<"清空栈操作:"<<endl; 57 if(ClearStack(S)) 58 printStack(S); 59 60 //销毁栈 61 62 cout<<"销毁栈操作:"<<endl; 63 DestroyStack(S); 64 cout<<"S.base = "<<S.base<<" S.top = "<<S.top<<" S.size= "<<S.size<<endl; 65 system("pause"); 66 return 0; 67 68 } 69 70 /******************************************************** 71 * printStack 72 * 打印栈中的元素,自顶向下显示 73 ********************************************************/ 74 void printStack(struct Stack &S) 75 { 76 int n = S.top-S.base; 77 int index; 78 if(n==0) 79 { 80 cout<<".................................."<<endl; 81 cout<<"Stack is Empty..."<<endl; 82 cout<<".................................."<<endl; 83 return; 84 } 85 cout<<".................................."<<endl; 86 cout<<"栈中的数据(从栈顶元素开始向下显示)"<<endl; 87 for(index=1;index<=n;++index) 88 { 89 cout<<*(S.top - index)<<" "; 90 } 91 cout<<endl; 92 } 93 94 /******************************************************** 95 * InitStack 96 * 动态分配内存 97 * 并对栈的属性初始化 98 ********************************************************/ 99 bool InitStack(struct Stack &S) 100 { 101 S.base = (int* )malloc(STACK_SIZE *sizeof(Stack)); 102 if(NULL == S.base) 103 { 104 cout<<"malloc stack error!"<<endl; 105 return false; 106 } 107 S.top = S.base; // init stack is empty 108 S.size = STACK_SIZE; 109 return true; 110 } 111 112 /******************************************************** 113 * ClearStack 114 * 清空栈内数据 115 ********************************************************/ 116 bool ClearStack(struct Stack &S) 117 { 118 S.top = S.base; 119 return true; 120 } 121 122 /******************************************************** 123 * DestroyStack 124 * 销毁栈S,释放内存,并将指针属性置空,防止悬浮指针产生 125 ********************************************************/ 126 bool DestroyStack(struct Stack &S) 127 { 128 free(S.base); 129 S.base =NULL; // 防止悬浮指针 130 S.top = NULL; // 防止悬浮指针 131 S.size =0; 132 return true; 133 } 134 135 /******************************************************** 136 * IsEmpty 137 * 判断栈是否为空 138 * 若栈顶指针(S.top)和栈底指针(S.base)相等 139 * 则表示站内没有数据 140 ********************************************************/ 141 bool IsEmpty(struct Stack &S) 142 { 143 if(S.top == S.base) return true; 144 else return false; 145 } 146 147 /******************************************************** 148 * IsFull 149 * 判断栈是否存满了数据 150 * A = S.top - S.base 表示栈中当前实际存储了多少元素 151 * B = S.size 则表示栈的容量。 152 * 若A>=B,则表示栈溢出 153 ********************************************************/ 154 bool IsFull(struct Stack &S) 155 { 156 if((S.top-S.base) >= STACK_SIZE) 157 { 158 cout<<"Stack is Full"<<endl; 159 return true; 160 } 161 else return false; 162 } 163 /******************************************************** 164 * Push 165 * 压栈操作 166 * 栈是特殊的线性表,其不支持随机访问,因此只能按照顺序存储。 167 * 例如:子弹夹上子弹(该例子与本实现不同的是 168 * ++子弹夹栈顶指针保持不变,栈底指针游动。 169 * ++本程序实现的是栈底指针不变,栈顶指针游动。) 170 ********************************************************/ 171 void Push(struct Stack &S, int e) 172 { 173 if(!IsFull(S)) 174 { 175 *(S.top) = e; 176 S.top ++; 177 } 178 } 179 /******************************************************** 180 * Push 181 * 弹栈操作 182 * 栈是特殊的线性表,其不支持随机访问,因此只能按照顺序存储。 183 * 例如:子弹夹推出子弹(该例子与本实现不同的是 184 * ++子弹夹栈顶指针保持不变,栈底指针游动。 185 * ++本程序实现的是栈底指针不变,栈顶指针游动。) 186 ********************************************************/ 187 void Pop(struct Stack &S, int &e) 188 { 189 if(IsEmpty(S)) 190 { 191 cout<<"Pop error"<<endl; 192 } 193 else 194 { 195 e = *(S.top-1); 196 S.top --; 197 } 198 }