栈的链式存储和顺序存储的基本操作

一、闵版(顺序存储单指针)

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.构建栈结构,主要是要注意栈先进后出,后进先出的特性。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值