目录
一、闵版(顺序存储单指针)
1.完整代码
#include <stdio.h>
#include <iostream>
using namespace std;
#define MaxSize 10
typedef struct _Stack
{
int top;
int data[MaxSize];
}*CharStackPtr;
void outputStack(CharStackPtr paraStack)
{
for(int i = 0;i<=paraStack->top;i++)
{
cout<<paraStack->data[i]<<" ";
}
cout<<endl;
}
CharStackPtr charStackInit()
{
CharStackPtr resultPtr = new struct _Stack;
resultPtr->top = -1;
return resultPtr;
}
void push(CharStackPtr paraStackPtr, int paraValue)
{
// Step 1. Space check.
if(paraStackPtr->top >= MaxSize-1)
{
cout<<"Cannot push element: stack full.";
return;
}
// Step 2. Update the top.
paraStackPtr->top++;
// Step 3. Push element.
paraStackPtr->data[paraStackPtr->top] = paraValue;
}
int pop(CharStackPtr paraStackPtr)
{
// Step 1. Space check.
if(paraStackPtr->top < 0)
{
cout<<"Cannot pop element: stack empty."<<endl;
return '\0';
}
// Step 2. Update the top.
paraStackPtr->top--;
// Step 3. Pop element.
return paraStackPtr->data[paraStackPtr->top + 1];
}
void pushPopTest() {
printf("---- pushPopTest begins. ----\r\n");
// Initialize.
CharStackPtr tempStack = charStackInit();
printf("After initialization, the stack is: ");
outputStack(tempStack);
// Poush.
for (int i = 0; i < 5; i++) {
printf("Pushing %d.\r\n", i);
push(tempStack, i);
outputStack(tempStack);
}
// Pop.
for (int i = 0; i < 3; i ++) {
int ch = pop(tempStack);
printf("Pop %d.\r\n", ch);
outputStack(tempStack);
}
printf("---- pushPopTest ends. ----\r\n");
}
int main() {
pushPopTest();
system("pause");
}
2.运行结果
二、钦版(顺序存储双指针)
1.栈的示意图
单向进出,先进后厨,后进先出,就像一个死胡同一样。
2.结构体的创建
typedef struct _SqStack
{
ElemType *base;//栈底指针
ElemType *top;//栈顶指针
}SqStack;
3.栈的初始化
bool InitStack(SqStack &S)//构造一个空栈
{
S.base = new ElemType[MaxSize];//为栈分配一个MaxSize容量的空间
if(!S.base)//内存分配失败
return false;
S.top = S.base;//空栈
return true;
}
4.压栈——元素入栈
//插入元素e为新的栈顶元素
bool PushStack(SqStack &S,ElemType e)
{
if( (S.top - S.base) == MaxSize)//栈满
return false;
*(S.top++) = e;//元素e 入栈,栈顶指针向上引动 等价于 S.top = e; S.top++;
return true;
}
5.出栈(只能从后面依次出栈)
//删除S的栈顶元素,暂存在变量e中,方便后续查看删除的是谁
bool PopStack(SqStack &S,ElemType &e)
{
if(S.base == S.top)//栈空城
return false;
e = *(--S.top);//由于S.top比较勤奋 ,指向的是栈顶的上一位,所以要先 -- 指向栈顶数据,再赋值
return true;
}
先进后出,后进先出是栈的特性。
6.获取栈顶元素
/*获取栈顶元素*/
ElemType GetTop(SqStack &S)
{
if(S.top!=S.base)//栈非空
return *(S.top-1);
else
return 0;
}
7.栈中元素的个数
//返回栈中元素个数
int GetSize(SqStack &S)
{
return(S.top-S.base);
}
8.判断是否为空
//判断栈是否为空
bool IsEmpty(SqStack &S)
{
if(S.top == S.base)//空
return true;
else
return false;
}
9.判断是否为满
bool IsFull(SqStack &S)
{
if((S.top -S.base) == MaxSize)//空
return true;
else
return false;
}
10.摧毁栈
void DestoryStack(SqStack &S)
{
if(S.base)
{
delete(S.base);
S.base = NULL;
S.top = NULL;
cout<<endl<<"销毁成功!";
}else
cout<<"\n销毁失败!"<<endl;
}
11.完整代码
#include <Windows.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#define MaxSize 128//预先分配空间,这个数值根据实际需要预估确定
typedef int ElemType;
/*作业 :采用如下方法
typedef struct _SqStack
{
int top;//栈顶指针
ElemType *top;//栈底指针
}SqStack;
*/
typedef struct _SqStack
{
ElemType *base;//栈底指针
ElemType *top;//栈顶指针
}SqStack;
bool InitStack(SqStack &S)//构造一个空栈
{
S.base = new ElemType[MaxSize];//为栈分配一个MaxSize容量的空间
if(!S.base)//内存分配失败
return false;
S.top = S.base;//空栈
return true;
}
//插入元素e为新的栈顶元素
bool PushStack(SqStack &S,ElemType e)
{
if( (S.top - S.base) == MaxSize)//栈满
return false;
*(S.top++) = e;//元素e 入栈,栈顶指针向上引动 等价于 S.top = e; S.top++;
return true;
}
//删除S的栈顶元素,暂存在变量e中
bool PopStack(SqStack &S,ElemType &e)
{
if(S.base == S.top)//栈空城
return false;
e = *(--S.top);//由于S.top比较勤奋 ,指向的是栈顶的上一位,所以要先 -- 指向栈顶数据,再赋值
return true;
}
//法一:返回S的栈顶元素,栈顶指针不变
ElemType GetTop(SqStack &S)
{
if(S.top!=S.base)//栈非空
return *(S.top-1);
else
return 0;
}
//法二:
bool GetTop2(SqStack &S,ElemType &e)
{
if(S.top!=S.base)//栈非空
{
e = *(S.top-1);
return true;
}else
return false;
}
//返回栈中元素个数
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)
{
delete(S.base);
S.base = NULL;
S.top = NULL;
cout<<endl<<"销毁成功!";
}else
cout<<"\n销毁失败!";
}
void Test()
{
int num,x;
SqStack S;
//1.初始化栈
InitStack(S);
//2.元素的插入
cout<<"请输入插入元素的个数:"<<endl;
cin>>num;
printf("依次输入%d个元素:",num);
while(num>0)
{
cin>>x;
PushStack(S,x);
num--;
}
cout<<"\n依次出栈结果如下:"<<endl;
//3.获取栈顶元素并出栈
while(!IsEmpty(S))
{
cout<<GetTop(S)<<" ";//输出栈顶元素
PopStack(S,x);//栈顶元素出栈
}
cout<<endl;
DestoryStack(S);
}
int main()
{
Test();
return 0;
}
12.运行结果
如果只是想单纯的查看栈中的元素,而不要元素出栈的方式可以借鉴“闵版的顺序存储方式”。“钦版的顺序存储是采用双指针”,一般出栈即删除。
三、钦版(链式存储)
1.结构体的创建
typedef struct _StackNode
{
int data;
struct _StackNode *next;
}Node,*NodePtr;
2.初始化栈
/*初始化栈*/
bool InitStack(NodePtr &Top)
{
Top = new struct _StackNode;
Top->next = NULL;
return true;
}
3.元素压栈
/*元素压栈*/
bool Push_Stack(NodePtr &Top,int e)
{
NodePtr p = new _StackNode;
if(!p)
return false;
p->data = e;//给此结点数据域赋值为e
p->next = Top->next;//新结点的指针域指向原来倒数第二个
Top->next = p; //栈顶指针指向新的结点
return true;
}
4.按任意位置压栈
/*按任意位置插入*/
bool insert_Stack(NodePtr &Top,int pos,int val)
{
NodePtr pMove = Top,q;
int i = 0;
/*如果是在第一个插入那么和压栈一样,那就直接采用压栈的方式吧*/
if(pos == 1)
{
if(Push_Stack(Top,val))
return true;
else
return false;
}
while(pMove && i<pos-1)
{
pMove = pMove->next;
i++;
}
if(i>pos-1 || !pMove)
{
cout<<"非法插入!"<<endl;
return false;
}
NodePtr pNew = new _StackNode;
pNew->data = val;
q = pMove->next;//指向插入点的位置
pMove->next = pNew;//更新pMove->next为新的结点
pNew->next = q;//新的结点指向原来pMove->next的指向
return true;
}
5.出栈
/*出栈*/
bool Pop_Stack(NodePtr &Top,int &e)
{
if(!Top->next)
return false;
NodePtr p;
p = Top->next;
e = p->data;
Top->next = p->next;
delete p;
return true;
}
6.获取栈顶元素
/*获取栈顶元素*/
bool GetTop(NodePtr &Top,int &e)
{
if(Top->next == NULL)
{
cout<<"栈顶为空!"<<endl;
return false;
}
e = Top->next->data;
}
7.获取栈长
/*获取栈长*/
int Get_Length(NodePtr &Top)
{
int num = 0;
NodePtr pMove = Top->next;
while(pMove != NULL)
{
num++;
pMove = pMove->next;
}
return num;
}
8.摧毁链栈
/*摧毁链栈*/
void Destory_Stack(NodePtr &Top)
{
if(Top)
{
delete Top;
cout<<endl<<"摧毁成功!"<<endl;
}else
cout<<endl<<"摧毁出错!"<<endl;
}
9.完整代码
#include <iostream>
using namespace std;
typedef struct _StackNode
{
int data;
struct _StackNode *next;
}Node,*NodePtr;
/*初始化栈*/
bool InitStack(NodePtr &Top)
{
Top = new struct _StackNode;
Top->next = NULL;
return true;
}
/*元素压栈*/
bool Push_Stack(NodePtr &Top,int e)
{
NodePtr p = new _StackNode;
if(!p)
return false;
p->data = e;//给此结点数据域赋值为e
p->next = Top->next;//新结点的指针域指向原来倒数第二个
Top->next = p; //栈顶指针指向新的结点
return true;
}
/*打印*/
void Print_Stack(NodePtr &Top)
{
NodePtr pMove = Top->next;
if(!pMove)
return;
cout<<"链栈打印结果如下:"<<endl;
while(pMove != NULL)
{
cout<<pMove->data<<" ";
pMove = pMove->next;
}
cout<<endl;
return;
}
/*出栈*/
bool Pop_Stack(NodePtr &Top,int &e)
{
if(!Top->next)
return false;
NodePtr p;
p = Top->next;
e = p->data;
Top->next = p->next;
delete p;
return true;
}
/*获取栈顶元素*/
bool GetTop(NodePtr &Top,int &e)
{
if(Top->next == NULL)
{
cout<<"栈顶为空!"<<endl;
return false;
}
e = Top->next->data;
}
/*获取栈长*/
int Get_Length(NodePtr &Top)
{
int num = 0;
NodePtr pMove = Top->next;
while(pMove != NULL)
{
num++;
pMove = pMove->next;
}
return num;
}
/*摧毁链栈*/
void Destory_Stack(NodePtr &Top)
{
if(Top)
{
delete Top;
cout<<endl<<"摧毁成功!"<<endl;
}else
cout<<endl<<"摧毁出错!"<<endl;
}
void Test()
{
NodePtr S = NULL;
//1.初始化
if(InitStack(S))
cout<<"初始化成功!!"<<endl<<endl;
//2.压栈
int len = 0;
cout<<"请输入压栈的次数:";
cin>>len;
cout<<"请输入压栈元素:";
for(int i=0;i<len;i++)
{
int data;
cin>>data;
Push_Stack(S,data);
Print_Stack(S);
}
//3.获取栈顶元素
int top_data = -1;
GetTop(S,top_data);
cout<<endl<<"栈顶元素为:"<<top_data<<endl;
//4,获取栈长
int length =Get_Length(S);
cout<<"栈长为:"<<length<<endl;
//5.出栈
int num = 0;
cout<<endl<<"请输入出栈次数:";
cin>>num;
for(int i = 0;i<num;i++)
{
int node;
Pop_Stack(S,node);
cout<<endl<<"删除"<<node<<"成功!"<<endl;
Print_Stack(S);
}
//6.摧毁链栈
Destory_Stack(S);
}
int main()
{
Test();
system("pause");
}
10.运行结果
四、总结
1.栈有顺序存储和链式存储两种方式。
2.顺序存储里也含有单指针和双指针两种结构方式。
3.构建栈结构,主要是要注意栈先进后出,后进先出的特性。