数据结构与算法——栈 特点与算法实现
1. 栈的特点
有一个胡同很窄只能通过一辆车,而且是死胡同,只能从胡同口进出,如果第一个进入,出去会很麻烦,需要所有的车辆出去后才能出去,如图:
胡同里的小汽车是排成一条直线,是线性排列,而且只能从一端进出,后进的汽车先出去,后进 先出(Last In First Out,LIFO),这就是"栈"。栈也是一种线性表,只不过它是操作受限的线性 表,只能在一端操作。 进出的一端称为栈顶(top),另一端称为栈底(base)。栈可以用顺序存储,也可以用链式存储。 我们先看顺序存储方式:
其中,base 指向栈底,top 指向栈顶。
注意:栈只能在一端操作,后进先出,这是栈的关键特征,也就是说不允许在中间查找、取值、插入、删除等 操作,我们掌握好顺序栈的初始化、入栈,出栈,取栈顶元素等操作即可。
2.栈的算法实现
2.1 栈数据结构的定义
1 #define MaxSize 128 //预先分配空间,这个数值根据实际需要预估确定 2 3 typedef int ElemType; 4 5 typedef struct _SqStack 6 { 7 ElemType *base; //栈底指针 8 ElemType *top; //栈顶指针 9 }SqStack;
2.2 栈的初始化
1 bool InitStack(SqStack &S) //构造一个空栈 S 2 { 3 S.base = new int[MaxSize]; //为顺序栈分配一个最大容量为 Maxsize 的空间 4 5 if (!S.base) //空间分配失败 6 return false; 7 8 S.top=S.base; //top 初始为 base,空栈 9 10 return true; 11 }
2.3 入栈
入栈操作:判断是否栈满,如果栈已满,则入栈失败,否则将元素放入栈顶,栈顶指针向上移动一个空间(top++)。
1 bool PushStack(SqStack &S, int e) // 插入元素 e 为新的栈顶元素 2 { 3 if (S.top-S.base == MaxSize) //栈满 4 return false; 5 6 *(S.top++) = e; //元素 e 压入栈顶,然后栈顶指针加 1,等价于*S.top=e; S.top++; 7 8 return true; 9 }
2.4 出栈
出栈操作: 和入栈相反,出栈前要判断是否栈空,如果栈是空的,则出栈失败,否则将栈顶元素暂存给一个变 量,栈顶指针向下移动一个空间(top--)。
1 bool PopStack(SqStack &S, ElemType &e) //删除 S 的栈顶元素,暂存在变量e中 2 { 3 if (S.base == S.top) //栈空 4 { 5 return false; 6 } 7 e = *(--S.top); //栈顶指针减 1,将栈顶元素赋给 e 8 9 return true; 10 }
2.5 获取栈顶元素
取栈顶元素和出栈不同,取栈顶元素只是把栈顶元素复制一份,栈的元素个数不变,而出栈是指栈顶元素取出, 栈内不再包含这个元素。
1 ElemType GetTop(SqStack &S) //返回 S 的栈顶元素,栈顶指针不变 2 { 3 if (S.top != S.base) //栈非空 4 { 5 return *(S.top - 1); //返回栈顶元素的值,栈顶指针不变 6 } 7 else 8 { 9 return -1; 10 } 11 }
2.6 判断是否空栈
1 bool IsEmpty(SqStack &S) //判断栈是否为空 2 { 3 if (S.top == S.base) 4 { 5 return true; 6 } 7 else 8 { 9 return false; 10 } 11 }
3. 完整实现
1 #include <Windows.h> 2 #include <iostream> 3 #include <stdlib.h> 4 5 using namespace std; 6 7 #define MaxSize 128 //预先分配空间,这个数值根据实际需要预估确定 8 9 typedef int ElemType; 10 11 typedef struct _SqStack 12 { 13 ElemType *base; //栈底指针 14 ElemType *top; //栈顶指针 15 }SqStack; 16 17 bool InitStack(SqStack &S) //构造一个空栈 S 18 { 19 S.base = new ElemType[MaxSize]; //为顺序栈分配一个最大容量为 Maxsize 的空间 20 if (!S.base) //空间分配失败 21 return false; 22 23 S.top=S.base; //top 初始为 base,空栈 24 return true; 25 } 26 27 bool PushStack(SqStack &S, ElemType e) //插入元素 e 为新的栈顶元素 28 { 29 if (S.top-S.base == MaxSize) //栈满 30 return false; 31 *(S.top++) = e; //元素 e 压入栈顶,然后栈顶指针加 1,等价于*S.top=e; S.top++; 32 33 return true; 34 } 35 36 bool PopStack(SqStack &S, ElemType &e) //删除 S 的栈顶元素,暂存在变量 e 中 37 { 38 if (S.base == S.top) //栈空 39 { 40 return false; 41 } 42 e = *(--S.top); //栈顶指针减 1,将栈顶元素赋给 e 43 44 return true; 45 } 46 47 ElemType GetTop(SqStack &S) //返回 S 的栈顶元素,栈顶指针不变 48 { 49 if (S.top != S.base) //栈非空 50 { 51 return *(S.top - 1); //返回栈顶元素的值,栈顶指针不变 52 } 53 else 54 { 55 return -1; 56 } 57 } 58 59 int GetSize(SqStack &S) //返回栈中元素个数 60 { 61 return (S.top-S.base); 62 } 63 64 bool IsEmpty(SqStack &S) //判断栈是否为空 65 { 66 if (S.top == S.base) 67 { 68 return true; 69 } 70 else 71 { 72 return false; 73 } 74 } 75 76 void DestoryStack(SqStack &S) 77 { 78 if(S.base) 79 { 80 free(S.base); 81 S.base = NULL; 82 S.top = NULL; 83 } 84 85 } 86 int main() 87 { 88 int n,x; 89 SqStack S; 90 InitStack(S); //初始化一个顺序栈 S 91 92 cout <<"请输入元素个数 n:" <<endl; 93 cin>>n; 94 cout <<"请依次输入 n 个元素,依次入栈:" <<endl; 95 96 while(n--) 97 { 98 cin>>x; //输入元素 99 PushStack(S, x); 100 } 101 102 cout <<"元素依次出栈:" <<endl; 103 104 while(!IsEmpty(S)) //如果栈不空,则依次出栈 105 { 106 cout<<GetTop(S)<<"\t"; //输出栈顶元素 107 PopStack(S, x); //栈顶元素出栈 108 } 109 110 cout <<endl; 111 DestoryStack(S); 112 113 system("pause"); 114 return 0; 115 }