【栈与队列】之栈的顺序存储(图文详细介绍!!)

前言:本章基于《大话数据结构》和王卓老师的视频内容,为刚接触数据结构的初学者提供一些帮助。

💕如果我的文章对你有帮助,点赞、收藏、留言都是对我最大的动力


目录

4.1 栈的定义

4.2 栈的抽象数据类型

4.3 栈的顺序存储结构及实现

4.4 完整代码


4.1 栈的定义

栈:是限定仅在表尾进行插入和删除操作的线性表

允许插入和删除的一端称为栈顶,另一端称为栈底。

空栈:不包含任何数据元素的栈称为空栈。

栈又称为后进先出的线性表,简称LIFO结构。

进栈(插入操作):也称为压栈、入栈。

出栈(删除操作):也叫做弹栈。

举例:有三个整数1、2、 3依次进栈,会出现几种出栈次序呢?

  • 第一种:1、2、3进,再3 、2、 1出
  • 第二种: 1进, 1出 ,2进, 2出, 3进,3出。也就是进一个就出一个,出栈为1、2、3。
  • 第三种: 1进,  2进,  2出,1出, 3进,3出。出栈次序为2、1、3。
  • 第四种:1进,1出,2进,3进,3出,2出。出栈次序为1、3、2。
  • 第五种:1进,   2进,  2出,3进,3出,1出。出栈次序为2、3、1。

栈与一般线性表的异同:

                         一般线性表
逻辑结构                            一对一一对一
存储结构                        顺序表、链表顺序栈、链栈
运算规则                            随机存取后进先出

4.2 栈的抽象数据类型

ADT Stack{

  数据对象:D={_{a_{i}}|_{a_{i}}属于Elemset,(i=1,2,3...,n,n\geqslant0}

  数据关系:R={<a_{i-1},a_{i}>|a_{i-1},a_{i},属于D,(i=2,3,...,n)}

                    约定an端为栈顶,a1端为栈底。

  基本操作:初始化、进栈、出栈、取栈顶元素等

}ADT Stack

4.3 栈的顺序存储结构及实现

存储方式:同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元依次存放自栈底 到栈顶的数据元素。栈底一般在低地址端。

top指针,指示栈顶元素在顺序栈中的位置。 base指针,指示栈底元素在顺序栈中的位置。

stacksize表示栈可使用的最大容量。

 栈的结构定义:

#define MAXSIZE 100
typedef struct{
    SElemType *base;//SElemType是自定义类型,base是栈底指针
    SElemType *top;//top是栈顶指针
    int stacksize;//栈可用最大容量
}SqStack;

顺序栈的初始化:

Status lnitStack(SqStack& S)//这里的S不是结构体指针所以下面可以不用S->
{
	S.base = (SElemType*)malloc(MAXSIZE*sizeof(SElemType));//动态分配
	//S.base = new SElemType[MAXSIZE];//C++的分配,这里其实是指向数组的首元素的地址
	
	if (!S.base)
		exit(OVERFLOW);//存储失败
	S.top = S.base;//栈顶指针等于栈底指针
	S.stacksize = MAXSIZE;
	return OK;
}

判断顺序栈是否为空:

算法分析:栈为空的话,top指针==base指针

Status StackEmpty(SqStack S)
{
	if (S.top = S.base)//如果栈顶和栈底相等,则为空
		return TRUE;
	else
		return FALSE;
}

求顺序栈的长度:

算法分析:S.stacksize=S.top-S.base

int StackLength(SqStack S)
{
	return S.top - S.base;
}

清空顺序栈:

Status ClearStack(SqStack S)
{
	if (S.base)S.top = S.base;//base存在这样一个地址,则top指针下移
	return OK;
}

销毁顺序栈:

Status DestroyStack(SqStack& S)
{
	if (S.base)
	{
		delete S.base;//我们在删除一个指针之后,编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身。
		//free(S.base);
		S.stacksize = 0;
		S.base = S.top = NULL;//不设置为空,则成为野指针
	}
	return OK;
}

顺序栈的入栈:

算法分析:

  1. 判断是否栈满,若满则出错(上溢)
  2. 元素e压入栈顶
  3. 栈顶指针加1

Status Push(SqStack& S, SElemType e)
{
	if (S.top - S.base == S.stacksize)//栈满
		return ERROR;
	*S.top++ = e;//取值,然后给他赋值,然后S.top++
	return OK;
}

顺序栈的出栈:

算法分析:

  1. 判断是否栈空,若满则出错(上溢)
  2. 获取栈顶元素e
  3. 栈顶指针减1

Status Pop(SqStack& S, SElemType& e)//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK
{
	if (S.top == S.base)//等价于if(StackEmpty(S))
		return ERROR;
	e = *--S.top;//相当与--S.top; e=*S.top
	return OK;
}

4.4 完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

#include <malloc.h>
#define MAXSIZE 100
#define OK 1
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2
#define ERROR 0
typedef int  SElemType;
typedef int Status;

//顺序栈的初始化
typedef struct
{
	SElemType* base;//栈底指针
	SElemType* top;//栈顶指针
	int stacksize;//栈可用最大容量
}SqStack;
Status lnitStack(SqStack& S)//这里的S不是结构体指针所以下面可以不用S->
{
	S.base = (SElemType*)malloc(MAXSIZE*sizeof(SElemType));//动态分配
	//S.base = new SElemType[MAXSIZE];//C++的分配,这里其实是指向数组的首元素的地址
	
	if (!S.base)
		exit(OVERFLOW);//存储失败
	S.top = S.base;//栈顶指针等于栈底指针
	S.stacksize = MAXSIZE;
	return OK;
}
//顺序栈判断栈是否为空
Status StackEmpty(SqStack S)
{
	if (S.top = S.base)//如果栈顶和栈底相等,则为空
		return TRUE;
	else
		return FALSE;
}
//求顺序栈的长度
int StackLength(SqStack S)
{
	return S.top - S.base;
}
//清空顺序栈
Status ClearStack(SqStack& S)
{
	if (S.base)
		S.top = S.base;//base存在这样一个地址,则top指针下移
	return OK;
}
//销毁顺序栈
Status DestroyStack(SqStack& S)
{
	if (S.base)
	{
		delete S.base;//我们在删除一个指针之后,编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身。
		//free(S.base);
		S.stacksize = 0;
		S.base = S.top = NULL;//不设置为空,则成为野指针
	}
	return OK;
}

//顺序栈的入栈
Status Push(SqStack& S, SElemType e)
{
	if (S.top - S.base == S.stacksize)//栈满
		return ERROR;
	*S.top++ = e;//取值,然后给他赋值,然后S.top++
	return OK;
}

//顺序栈的出栈
Status Pop(SqStack& S, SElemType& e)//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK
{
	if (S.top == S.base)//等价于if(StackEmpty(S))
		return ERROR;
	e = *--S.top;
	return OK;
}
//顺序栈的遍历
Status printList(SqStack S)
{
	SElemType* p;

	if (S.top == S.base) {
		printf("Stack is NULL.\n");
		return 0;
	}
	p = S.top;
	// 由栈顶依次向下遍历
	while (p > S.base) {
		p--;
		printf("%d ", *p);
	}
	printf("\n");
	return 1;

}
int main()
{
	SqStack S;
	SElemType e,n,i;
	lnitStack(S);//初始化
	printf("input the length of the Stack :\n");
	scanf("%d", &n);
	for (i = 1; i <= n; i++) {
		scanf("%d", &e);
		Push(S, e);//入栈
	}
	printList(S);//遍历
	printf("长度为:%d\n",StackLength(S));
	ClearStack(S);//清空栈
	printList(S);
	printf("长度为:%d\n", StackLength(S));
	DestroyStack(S);//销毁栈
	printList(S);
	printf("长度为:%d", StackLength(S));

}

  • 15
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
队列是两种常见的线性数据结构,它们都可以用于数据的存储和操作。 (Stack)是一种先进后出(LIFO,Last In First Out)的数据结构的定义是一个有序的元素集合,可以通过顶的位置进行访问和操作。的基本操作包括入栈(push)和出栈(pop)。入栈操作将一个元素放入栈顶,出栈操作将顶元素移除并返回。除此之外,还有获取顶元素(peek)和判断是否为空(isEmpty)的操作。 队列(Queue)是一种先进先出(FIFO,First In First Out)的数据结构队列的定义是一个有序的元素集合,可以通过队首和队尾的位置进行访问和操作。队列的基本操作包括入队(enqueue)和出队(dequeue)。入队操作将一个元素放入队尾,出队操作将队首元素移除并返回。除此之外,还有获取队首元素(peek)和判断队列是否为空(isEmpty)的操作。 队列顺序存储结构可以使用数组来实现。对于而言,可以使用数组的一端作为顶,并通过指针或索引记录顶位置。对于队列而言,可以使用数组的两端作为队首和队尾,并通过指针或索引记录队首和队尾位置。 的基本运算包括: - 入栈(push):将元素放入栈顶; - 出栈(pop):将顶元素移除并返回; - 获取顶元素(peek):返回顶元素但不移除; - 判断是否为空(isEmpty):判断中是否没有元素。 队列的基本运算包括: - 入队(enqueue):将元素放入队尾; - 出队(dequeue):将队首元素移除并返回; - 获取队首元素(peek):返回队首元素但不移除; - 判断队列是否为空(isEmpty):判断队列中是否没有元素。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值