数据结构 栈的结构特点及基本操作

栈的结构特点和操作

是限定只能在表的一端进行插入和删除的线性表,在表中,允许插入和删除的一端称为“栈顶”,不允许插入和删除的一端称为“栈底”。栈的元素进出是按照“先进后出,后进先出”的顺序进行。和线性表类似,栈也有两种存储方法顺序栈和链栈

顺序栈

顺序栈是指利用顺序存储分配实现的栈。同时附设top指针指示栈顶元素在顺序栈中的位置。用一维数组来描述顺序栈中数据元素的存储区域,并预设一个最大的存储空间。对于top指针,由于数组的第一个元素的下标为0,所以初始化top=-1;表示是个空栈。输出栈内数据元素时,可以利用循环变量 i <= S.top;来输出。由于顺序栈的插入和删除只能在栈顶进行,所以顺序栈的一些相关操作比顺序表要简单的多。具体C语言实现代码如下:

#include<stdio.h>

#define TRUE 1
#define FALSE 0
/***************************************************************************************************
									  栈的顺序存储表示
****************************************************************************************************/
const int STACK_INIT_SIZE = 100;   //顺序栈默认的初始分配最大空间量
const int STACKINCREMENT = 10;     //默认的增补空间量
typedef struct {
	int *elem;             //存储数据的数组
	int top;              //栈顶指针
	int stacksize;         //当前分配的最大容量
	int incrementsize;     //约定的增补空间量
}SqStack;

/*****************************************************************************************************
									          建表
******************************************************************************************************/
void InitStack_Sq(SqStack &S, int maxsize = STACK_INIT_SIZE, int incresize = STACKINCREMENT)
{
	//构造一个空栈S,初始化分配的最大空间为maxsize,预设的增补空间量为incresize
	S.elem = new int[maxsize];        //为顺序栈分配最大容量为maxsize的数组空间
	S.top = -1;                       //顺序栈中当前所含元素个数为零
	S.stacksize = maxsize;            //该顺序栈可容纳maxsize个数据元素
	S.incrementsize = incresize;      //需要时每次扩容incresize个元素的空间
}

/***************************************************************************************************
                                      返回栈顶元素
****************************************************************************************************/
bool GetTop_Sq(SqStack S, int &e)
{
	//若栈不空,用e返回栈顶元素并返回TRUE,否则返回FALSE
	if (S.top == -1)
		return FALSE;
	e = S.elem[S.top];
	return TRUE;
}

/*****************************************************************************************************
											插入
******************************************************************************************************/
void incrementStacksize(SqStack &S)
{
	int *a;
	a = new int[S.stacksize + S.incrementsize];
	for (int i = 0; i <=S.top; i++)
		a[i] = S.elem[i];
	delete[]S.elem;
	S.elem = a;
	S.stacksize = S.stacksize + S.incrementsize;
}

void Push_Sq(SqStack &S, int e)
{
	//插入元素e为新的栈顶元素
	if (S.top == S.stacksize - 1)
		incrementStacksize(S);       //若空间不够则扩容重新分配空间,类似于顺序表
	S.elem[++S.top] = e;
}

/*****************************************************************************************************
												删除
******************************************************************************************************/
bool Pop_Sq(SqStack &S, int &e)
{
	//若栈不空,则删除S的栈顶元素,并用e返回其值,并返回TRUE,否则饭返回FALSE
	if (S.top == -1)
		return FALSE;
	e = S.elem[S.top--];
	return TRUE;
}

/******************************************************************************************************
											主函数
*******************************************************************************************************/
void main()
{
	int i;
	int e1;       //用于接收栈顶元素
	int e2 = 11;  //用于插入新的栈顶元素
	int e3;       //用于接收删除的栈顶元素
	SqStack S;
	InitStack_Sq(S);
	for (i = 0; i < 10; i++)
	{
		S.elem[i] = i + 1;
		S.top++;
	}
	printf("顺序栈中数据元素为:");
	for (i = 0; i <= S.top; i++)
		printf("%d ", S.elem[i]);
	printf("\n");
	if (GetTop_Sq(S, e1))
		printf("返回此时栈顶元素为:%d\n", e1);
	else
		printf("这是一个空栈。\n");
	Push_Sq(S, e2);
	printf("插入新的栈顶元素后新栈的数据元素为:");
	for (i = 0; i <= S.top; i++)
		printf("%d ", S.elem[i]);
	printf("\n");
	if (Pop_Sq(S, e3))
	{
		printf("删除的栈顶元素为%d,删除后的栈内数据元素为:",e3);
		for (i = 0; i <= S.top; i++)
			printf("%d ", S.elem[i]);
	}
	else
		printf("这是一个空栈。");
}

链栈

链栈是利用链式分配实现的栈。对于顺序栈,虽然在满员状态下可以重新分配空间扩容,但是也是不得已而为之,所以当无法预先估计栈可能达到的最大容量时,应该采用链栈更合适。链栈的结点结构和链表的结点结构相同,值得注意的是,链栈中指针的方向是从栈顶指向栈底。

同顺序栈一样,链栈相比于单链表来说操作也简单了不少。值得注意的是,对于需要用 e 返回数值的函数来说,定义函数时形参部分需要用 int &e;来表示。原因是函数是布尔类型的函数,若要让e的值改变,需要传地址进入函数,所以用&e。同时,对于链栈的赋值,可以用提前赋好值的数组,也可以用scanf函数进行赋值,本质上是不断调用 void Push_L(LinkStack &S, int e) 插入函数。


#include<stdio.h>
#define TRUE 1
#define FALSE 0

/**********************************************************************
							定义结构类型
***********************************************************************/
typedef struct LNode {
	int data;
	struct LNode *next;
}LNode, *LinkStack;

/************************************************************************
								  建表
************************************************************************/
void InitStack_L(LinkStack &S)
{
	//创建一个空的链栈,即设栈顶指针为空
	S = NULL;
}
/*************************************************************************
									插入
**************************************************************************/
void Push_L(LinkStack &S, int e)
{
	//在链栈的栈顶插入新的栈顶元素e
	LNode *p = new LNode;     //为新的栈顶元素分配结点
	p->data = e;
	p->next = S;              //插入新的栈顶元素
	S = p;                    //修改栈顶指针
}
/***************************************************************************
								删除
****************************************************************************/
bool Pop_L(LinkStack &S, int &e)
{
	//若栈不空则删除栈顶元素,并用e返回其值,并返回TRUE,否则返回FALSE
	if (S)
	{
		LNode *p;
		p = S;
		S = S->next;    //修改栈顶指针
		e = p->data;    //返回栈顶元素
		delete p;       //释放结点空间
		return TRUE;
	}
	else
		return FALSE;
}

/******************************************************************************
                             从栈底到栈顶依次输出
*******************************************************************************/
void StackTraverse(LinkStack S)
{
	LinkStack SS;    //辅助栈 用来逆序输出
	SS = NULL;
	LNode *p;    //用来遍历目标栈的指针
	p = S;
	while (p != NULL)
	{
		LNode *s;
		s = new LNode;   //新建结点s用于插入辅助栈SS中
		s->data = p->data;
		s->next = SS;
		SS = s;
		p = p->next;
	}
	p = SS;
	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
}
/******************************************************************************
									主函数
*******************************************************************************/
void main()
{
	int i;
	int e1;      //用来接收新插入的数据元素
	int e2;      //用来返回删除的栈顶元素
	int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
	LinkStack S;
	LNode *p;
	InitStack_L(S);
	for (i = 0; i < 10; i++)
	{
		e1 = a[i];
		Push_L(S, e1);
	}
	printf("此链栈的数据元素为:");
	for (p = S; p != NULL; p = p->next)
		printf("%d ", p->data);
	printf("\n");
	if (Pop_L(S, e2))
	{
		printf("删除的栈顶元素为%d,删除后的栈内数据元素为:", e2);
		for (p = S; p != NULL; p = p->next)
			printf("%d ", p->data);
		printf("\n");
	}
	else
		printf("这是一个空栈。");
	printf("栈底到栈顶输出:");
	StackTraverse(S);
}

本笔记所依据的教材为严薇敏版的《数据结构及应用算法教程》

所引用的图片来源于华中师范大学云课堂

所有代码在Visual Studio 2017上均可正常运行

如有错误欢迎指出

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值