数据结构——栈

什么是栈

**定义:**是线性表的子集,一种特殊的线性表
一般的线性表的插入、删除、运算不受限制,而栈只能从一端操作(栈顶)
栈只能从一端操作、先进后出,这是属于人为规定的。即可以从栈中间取一个元素,并且程序可以运行,但这样就不是栈了,因为这不符合栈的定义
特点先进后出(或后进先出)
按存储结构分类
顺序栈
采用地址连续的存储空间(类似于数组)依次存储栈中数据元素,入栈和出栈运算都是在栈顶进行,而栈底位置是固定不变,可以将栈底位置设置在内存空间的起始处;栈顶位置是随入栈和出栈操作而变化,用一个整型变量top来记录当前栈顶元素在数组中的位置。
应用
栈顶指针往后移,把数据存放在栈顶位置,;出栈是删除栈顶元素,栈顶往前移
在这里插入图片描述
链栈
采用链式存储,每个结点的地址是不连续的,并且每个结点包含数据域(存储数据)和指针域(存储下一个结点的地址),和单链表相同,但链栈没有头节点,而且链栈只能从一端操作(栈的定义),即只能从一端插入、删除等
应用:和单链表类似
优点:不会出现栈满溢出的情况
顺序栈和链栈的区别:
顺序栈采用的是预先分配内存,有可能会内存不够,或内存浪费;链栈不会有这些情况,但是每个结点有一个指针域,增加内存的开销。元素比较多的话用链栈比较好,反之顺序栈比较好
在这里插入图片描述
顺序栈

#define Maxsize 100  //预先分配栈空间的大小,由世界情况确定
typedef struct stack
{
	ElemType data[Maxsize]; //ElemType:元素类型,根据自己需要定义,例如int、char、float以及自定义的类型;data[Maxsize]:定义数组的长度
	int top;  //栈顶指针
	int base; //栈底指针,一般可不定义
}SqStack;   

void InitStack(SqStack &st)  //初始化顺序栈
{
	st.top = -1;
}
void Push(SqStack *&st, ElemType e)  //入栈
{
	int i = 0;
	if (st.top == Maxsize - 1)  //入栈需要判断栈空间已满是否已满,如果栈已满,则入栈失败,如果依旧往栈里面存储数据,会导致栈满溢出的情况
	{
		printf("栈空间已满\n");
		return ;
	}
	else
	{
		st.top++;  //入栈先使栈顶指针加1(栈顶指针上移一位),在存储数据
		st.data[st.top] = n;
	}
}
void Pop(SqStack *&st, ElemType &n)  //出栈
{
	int i=0;
	if (st.top == -1)  //判断是否栈空,如果栈空则结束
	{
		printf("栈空\n");
	}
	else
	{
	    n = st.data[st.top];//出栈先取出栈顶数据,然后栈顶指针减一(栈顶指针移向下一位置)
		st.top--;
	}
}
void GetTop(SqStack *st, ElemType n)  //取栈顶元素
{
	if (st.top == -1)  //栈空时取栈顶元素没有意义
	{
		printf("栈空\n");
	}
	else
	{
		while(st.top != -1)
		{
			n = st.top;
		}
	}
}
void DestroyStack(SqStack st)//销毁栈
{}
int StackEmpty(SqStack st)  //判断栈是否为空,可用来作为结束循环语句的条件(例如:while(!StackEmpty()) )当栈空时结束循环
{
	if (st.top == -1)
	{
		printf("\n栈空\n");
		return 1;
	}
	return 0;
}

链栈

typedef struct LiStack  
{
	ElemType data;  //数据域
	struct LiStack *next;   //指针域
}LiStack;
void InitStack(LiStack *&st)  //初始化栈
{
    st=(LiStack *)malloc(sizeof(LiStack));
    st-

> 这里是引用

=NULL;
}
void Push(LiStack *&st, ElemType x)   //入栈,将新元素节点压入栈顶
{
    LiStack *p;
    p=(LiStack *)malloc(sizeof(LiStack));  //创建新的节点
    p->data=x;
    p->next=st;  //将st的地址赋值给新建节点p的指针域
    st=p;        //新栈的栈顶指针为p
}
void Pop(LiStack *&st,ElemType &x)   //出栈,将栈顶元素删除,让栈顶指针指向下一元素
{
    LiStack *p;
    if(st->next==NULL)
    {
        printf("栈空\n");
    }
    else
    {
        x=st->data;
        p=st;           //p指向栈顶元素
        st=st->next;    //st指向栈顶的下一节点
        delete p;       //释放原栈顶元素的空间
    }
}
ElemType GetTop(LiStack *st)  //取栈顶元素,复制栈顶元素的数据
{
    if(st->next==NULL)
    {
        printf("栈空\n");
    }
    else
    {
        return st->data;
    }
}
void DestroyStack(LiStack *&st)   //销毁栈
{
    LiStack *p=st,*q=st->next;
    while(q!=NULL)
    {
        free(p);
        p=q;
        q=q->next;
    }
    free(p);
}
int StackEmpty(LiStack *st)  //判断栈是否为空
{
	if (st == NULL)
		return 1;
	else
		return 0;
}

栈的应用

顺序栈
题目:进栈顺序为(1,2,3…n),给定出栈顺序,判断该出栈顺序是否合法

#include<stdio.h>
#define Maxsize 100
#define N 5
#pragma warning(disable:4996)
typedef struct SqQueue
{
	int data[Maxsize];
	int top;
}Sq;


void Push(Sq &, int);
void Pop(Sq &);
void GetTop(Sq, int &);
int StackEmpty(Sq);


void Push(Sq &st, int x)   //元素x进栈
{
	if (st.top > Maxsize - 1)
	{
		printf("栈空间已满\n");
	}
	else
	{
		st.top++;
		st.data[st.top] = x;
	}
}

void Pop(Sq &st)   //出栈
{
	if (st.top == -1)
	{
		printf("栈空\n");
	}
	else
	{
		st.top--;
	}
}

void GetTop(Sq st, int &x)  //获取栈顶元素
{
	if (st.top == -1)
		printf("栈空\n");
	else
		x = st.data[st.top];
}

int StackEmpty(Sq st)  //判断栈是否为空
{
	if (st.top == -1)
		return 1;
	else
		return 0;
}

int main()
{
	Sq st;
	st.top = -1;
	int a[N];   //存储出栈顺序
	int i, j = 0, t = 0,e;
	printf("请输入你想要检测的出栈序列:\n");
	for (i = 0; i < N; i++)
	{
		scanf("%d", &a[i]);
	}

	for (i = 1; i <= N; i++)     
	{
		Push(st, i);             //i进栈
		printf("%d进栈\n", i);
		while (!StackEmpty(st))  //判断栈是否为空,栈空返回1,非空返回0
		{
			GetTop(st, e);       //获取栈顶元素
			if (a[j] == e)       //每进栈一个元素,就判断该元素是否时下一个出栈的元素
			{
				Pop(st);
				printf("%d出栈\n", e);
				j++;
				t++;             //t记录已经出栈的个数
			}
			else
				break;
		}
	}
	if (t == N)  //判断出栈个数和进栈个数是否相同
	{
		printf("该顺序合法\n");
	}
	else
		printf("该顺序不合法\n");
	return 0;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020060615410680.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODk2NzY2,size_16,color_FFFFFF,t_70#pic_center)

链栈
链栈的基本操作

#include<stdio.h>
#include<malloc.h>
#define Maxsize 100
#define N 5
#pragma warning(disable:4996)
typedef struct LiStack
{
	int data;  //数据域
	struct LiStack *next;   //指针域
}LiStack;

void InitStack(LiStack *&st)  //初始化栈
{
	st = (LiStack *)malloc(sizeof(LiStack));
	st->next = NULL;
}

void Push(LiStack *&st, int x)   
{
	LiStack *p;
	p = (LiStack *)malloc(sizeof(LiStack));  
	p->data = x;
	p->next = st;  
	st = p;        
}
void Pop(LiStack *&st, int &x)   
{
	LiStack *p;
	if (st->next == NULL)
	{
		printf("栈空\n");
	}
	while (st->next != NULL)
	{
	
		x = st->data;
		p = st;           
		st = st->next;    
		printf("%d\t", x);
		free(p);      
	
	}
}
void GetTop(LiStack *st, int &x)  
{
	if (st->next == NULL)
	{
		printf("栈空\n");
	}
	else
	{
		x = st->data;
	}
}
void DestroyStack(LiStack *&st)   //销毁栈
{
	LiStack *p = st, *q = st->next;
	while (q != NULL)
	{
		free(p);
		p = q;
		q = q->next;
	}
	free(p);
}
int main()
{
	LiStack *st;
	int x;
	InitStack(st);   //初始化栈
	printf("1进栈\n");
	Push(st, 1);
	printf("2进栈\n");
	Push(st, 2);
	printf("3进栈\n");
	Push(st, 3);
	GetTop(st, x);
	printf("此时栈顶元素为%d\n", x);
	printf("出栈次序:");
	Pop(st, x);
	printf("\n销毁栈\n");
	free(st);
	return 0;
	![在这里插入图片描述](https://img-blog.csdnimg.cn/20200606221617723.png)
}

由于时间、水平、精力有限,文中难免会出现不准确的、甚至错误的地方,欢迎大佬看见的话批评指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值