C++ 数据结构算法 学习笔记(17) - 栈的原理精讲 (1)
原理精讲
Jack 家的胡同很窄,只能通过一辆车,而且是死胡同,只能从胡同口进出,画图
胡同里的小汽车是排成一条直线,是线性排列,而且只能从一端进出,后进的汽车先出去,后进 先出(Last In First Out,LIFO),这就是"栈"。栈也是一种线性表,只不过它是操作受限的线性 表,只能在一端操作。 进出的一端称为栈顶(top),另一端称为栈底(base)。栈可以用顺序存储,也可以用链式存储。 我们先看顺序存储方式:
其中,base 指向栈底,top 指向栈顶。
注意:栈只能在一端操作,后进先出,这是栈的关键特征,也就是说不允许在中间查找、取值、插入、删除等 操作,我们掌握好顺序栈的初始化、入栈,出栈,取栈顶元素等操作即可。
顺序栈的算法实现
栈数据结构的定义
#define MaxSize 128 //预先分配空间,这个数值根据实际需要预估确定
typedef int ElemType;
typedef struct _SqStack{
ElemType *base; //栈底指针
ElemType *top; //栈顶指针
}SqStack;
栈的初始化
bool InitStack(SqStack &S) //构造一个空栈 S
{
S.base = new int[MaxSize];//为顺序栈分配一个最大容量为 Maxsize 的空间
if (!S.base) //空间分配失败
return false;
S.top=S.base; //top 初始为 base,空栈
return true;
}
入栈
入栈操作:判断是否栈满,如果栈已满,则入栈失败,否则将元素放入栈顶,栈顶指针向上移动一个空间(top++)
bool PushStack(SqStack &S, int e) // 插入元素 e 为新的栈顶元素
{
if (S.top-S.base == MaxSize) //栈满
return false;
*(S.top++) = e; //元素 e 压入栈顶,然后栈顶指针加 1,等价于*S.top=e;
S.top++;
return true;
}
出栈
出栈操作: 和入栈相反,出栈前要判断是否栈空,如果栈是空的,则出栈失败,否则将栈顶元素暂存给一个变 量,栈顶指针向下移动一个空间(top–)。
bool PopStack(SqStack &S, ElemType &e) //删除 S 的栈顶元素,暂存在变量 e中
{
if (S.base == S.top)
{
return false;
}
e = *(--S.top); //栈顶指针减 1,将栈顶元素赋给 e
return true;
}
获取栈顶元素
取栈顶元素和出栈不同,取栈顶元素只是把栈顶元素复制一份,栈的元素个数不变,而出栈是指栈顶元素取出, 栈内不再包含这个元素。
ElemType GetTop(SqStack &S) //返回 S 的栈顶元素,栈顶指针不变
{
if (S.top != S.base){ //栈非空
return *(S.top - 1); //返回栈顶元素的值,栈顶指针不变
}
else{
return -1;
}
}
判断空栈
bool IsEmpty(SqStack &S){//判断栈是否为空
if (S.top == S.base){
return true;
}
else{
return false;
}
}
完整源码
完整源码实现
#include <Windows.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
#define MaxSize 128
typedef int ElemType;
typedef struct _SqStack {
ElemType* base;
ElemType* top;
}SqStack;
bool InitStack(SqStack& S)
{
S.base = new ElemType[MaxSize];
if (!S.base) return false;
S.top = S.base;
return true;
}
bool PushStack(SqStack& S, ElemType e)
{
if (S.top - S.base == MaxSize) return false;
*(S.top++) = e;
return true;
}
bool PopStack(SqStack& S, ElemType& e)
{
if (S.base == S.top) {
return false;
}
e = *(--S.top);
return true;
}
ElemType GetTop(SqStack& S)
{
if (S.top != S.base) {
return *(S.top - 1);
}
else {
return -1;
}
}
int GetSize(SqStack& S) {
return (S.top - S.base);
}
bool IsEmpty(SqStack& S) {
if (S.top == S.base) {
return true;
}
else {
return false;
}
}
void DestoryStack(SqStack& S)
{
if (S.base) {
free(S.base);
S.base = NULL;
S.top = NULL;
}
}
int main()
{
int n, x;
SqStack S;
InitStack(S);
cout << "Please enter the element number n:" << endl;
cin >> n;
cout << "Please accodingly enter the element to enter the stack:" << endl;
while (n--)
{
cin >> x;
PushStack(S, x);
}
cout << "The element comeout from the stack:" << endl;
while (!IsEmpty(S))
{
cout << GetTop(S) << "\t";
PopStack(S, x);
}
cout << endl;
DestoryStack(S);
system("pause");
return 0;
}
课后练习
如果把栈的结构体定义改为链表形式, 该如何实现操作栈的算法呢?
完整代码实现
#include <iostream>
#include <string>
using namespace std;
#define MAX_SIZE 128
#define DataType int
typedef struct _List
{
_List* next;
DataType element;
}List;
typedef struct _SqList_Stack
{
List* top;
int size;
int capacity;
}SqList_Stack;
bool Init_Stack(SqList_Stack& stack)
{
stack.size = 0;
stack.capacity = MAX_SIZE;
stack.top = new List;
if (!stack.top) return false;
stack.top->next = NULL;
return true;
}
bool Empty_Stack(SqList_Stack& stack)
{
if (stack.size == 0) return true;
return false;
}
bool Full_Stack(SqList_Stack& stack)
{
if (stack.size == stack.capacity) return true;
return false;
}
bool Push_Stack(SqList_Stack& stack, DataType element_v)
{
if (Full_Stack(stack)) return false;
List* node = new List;
node->element = element_v;
node->next =stack.top->next;
stack.top->next = node;
stack.size++;
return true;
}
bool Pop_Stack(SqList_Stack& stack, DataType* element_v)
{
if (Empty_Stack(stack)) return false;
List* tmp = stack.top->next;
*element_v = tmp->element;
stack.top->next = tmp->next;
delete tmp;
stack.size--;
return true;
}
bool Get_Head(SqList_Stack& stack, DataType* element_v)
{
if (Empty_Stack(stack)) return false;
List* tmp = stack.top->next;
*element_v = tmp->element;
return true;
}
int GetSize(SqList_Stack& stack)
{
return stack.size;
}
void Destroy_Stack(SqList_Stack& stack)
{
List* tmp = stack.top;
while (tmp)
{
List* next = tmp->next;
delete tmp;
tmp = next;
}
stack.top = NULL;
stack.size = 0;
}
int main()
{
int n, x;
SqList_Stack S;
int element;
Init_Stack(S);
cout << "Please enter the element number n:" << endl;
cin >> n;
cout << "Please accodingly enter the element to enter the stack:" << endl;
while (n--)
{
cin >> x;
Push_Stack(S, x);
}
cout << "The element comeout from the stack:" << endl;
while (!Empty_Stack(S))
{
Get_Head(S, &element);
cout << element << "\t";
Pop_Stack(S, &x);
}
cout << endl;
cout << "Ending the print function" << endl;
Destroy_Stack(S);
system("pause");
return 0;
}