4.数据结构:栈的顺序栈与链栈

一.栈的介绍

当我们对线性表的操作做出某种限定的时候,即为受限制的线性表,限定的同,线性表也会不同,限定的线性表主要表示为,栈和队列;

栈,也称堆栈,是一种限定的操作的线性结构。日常生活中常见栈的实例,例如,我们夏天逛超市时,可能会忍不住想买一瓶冰饮料喝,饮料放在冰柜里,可是,冰柜中放在靠外的饮料往往并不冰,而深处我们够不着的地方,才是我们想要的。这种情况类似于线性结构中的栈,其特点就是,只能从冰柜门将饮料放人,先放进冰柜的在最里面,只能最后拿出来,除此之外,还有坐电梯,洗碗,一摞书,交作业先交的放在下面。

栈的基本概念
栈:是一种特殊的线性表,对其操作限制在表的同端进行,具有 后进先出的特性,因此,栈又被称为后进先出LIFO(Last In First Out)表或先进后出 FILO (First In Last Out)表栈顶:指允许进行插人、删除操作的一端。通常用top来指示栈项元素的位置。
空栈:当表中没有元素时称为空栈。
栈底:指不允许进行操作的一一端,一般不需要指示。

二.顺序栈

1.顺序栈基本介绍
(1).栈是操作受限的线性表,其逻辑结构和线性表是一样的 ,因此栈的存储可以和一般线性表一样,主要有顺序栈和链栈,在实际使用中,大部分情况下,我们都使用顺序栈,这是因为在顺序栈中只允许在栈顶进行人栈和出栈工作,顺序表的插入删除时间复杂度高的缺点就不存在了,顺序存储又有实现容易,存储密度大等优点。
(2).栈的顺序存储结构简称顺序栈,和顺序表类似,顺序栈也用数组来存放栈中的元素,再设定一个整型变量来指示栈顶位置,通常这个变量设为top,称为栈顶指针。

2.顺序栈的基本运算
(1).顺序栈的基本运算包括栈的初始化、判栈空、判栈满、进栈、出栈、取栈顶元素等操作,这里仅给出栈的初始化、进栈和出栈的操作算法,请读者自行给出判断栈空、判断栈满、取栈顶元素等函数。
(2).若栈的大小为最大为10,下标从0开始,栈空时栈顶指针指向一1,栈满时顶指针指向9(即:最大值- 1)。

如图展示:
在这里插入图片描述

三.链栈

采用链表作为存储结构的栈及链栈,与链表相似,也可以说是被受限制的链表。通常为了方便操作附设了一个头节点是与链表的不同之处;
链栈在插入和删除操作仅限于表头位置进行,所以,栈顶就是表头指针;
在这里插入图片描述

四.顺序栈与链栈代码展示

(1).顺序栈代码:(入栈与出栈)

在这里插入代码片:
#include <iostream>
#include <stdlib.h>
using namespace std;

#define maxsize 100                                        //顺序栈最大的存储空间
#define NULL 0
#define OK 1
#define ERR 0
typedef int ElemType;                                      //顺序栈存储元素的类型
typedef struct  
{
	ElemType data[maxsize];                         
	int top;                                              //top栈顶元素,top实际并不是指针类型,存放的是栈顶元素的下标
}SqStack;

SqStack* InitSqStack()       //顺序栈的初始化
{
	SqStack* s;
	s = (SqStack*)malloc(sizeof(SqStack));               //申请顺序栈的空间
	if (!s)
	{
		return NULL;                                     //申请失败返回0
	}
	else
	{
		s->top = -1;                                     //申请成功设置为空栈,这样初始化成功
		return s;
	}
}

SqStack* AssignStack(SqStack *s)    //顺序栈的输入
{
	int i, lenghth;
	cout << "请输入顺序栈的长度" << endl;                            //输入栈的长度
	cin >> lenghth;
	cout << "请根据设定的长依次输入顺序栈的元素" << endl;
	for (int i = 0; i < lenghth; i++)
	{
		cin >> s->data[i];                                          //输入栈的元素
		s->top++;                                                   //栈顶不断向后移动
	}
	return s;
}
//顺序栈的插入
//将一个新的元素加入栈中,通常称为入栈和压栈
//算法思路:
//1.判断栈是否满,如果栈满了,给出提示,出错返回
//2.栈顶加1
//3.新元素赋值给栈顶
//4.完成返回
int Push(SqStack* s, ElemType x)
{
	if (s->top == maxsize - 1)                          //判断栈是否满了
	{                                                   //可以改改define的值,这样看看程序会不会出错
		return ERR;
	}
	else
	{
		s->top++;                                       //栈顶加1   
		s->data[s->top] = x;                            //将新元素的值赋值新栈顶
		return OK;
	}
}

//顺序栈的删除(出栈)
//将栈顶的元素删除
//算法思路:
//1.判断栈是否为空,若是空栈,则没有元素出栈,给出提示出错返回
//2.将栈顶元素赋值给x指针所指向的变量
//3.栈顶指针减1
//4.完成返回
int delepop(SqStack *s,ElemType *u)
{
	if (s->top == -1)
	{
		cout << "此栈为空栈" << endl;                             //判断是否为空栈(插入的就判断是否已经满了,删除判断是否为空)
		return ERR;
	}
	else
	{
		*u = s->data[s->top];                                     //将栈的元素赋值给一个新元素指针存着,之后在栈顶减一
		s->top--;      //其实这个函数还是在这个数组中,但它不在这个栈中,如果你加回来,在输出,还是能看到原来的数
		cout << "出栈成功" << endl;
		return OK;
	}
}

//顺序栈的输出显示
void OputSqlist(SqStack *s)
{
	int i;
	cout << "顺序表长度为:" << s->top+1 << endl;
	cout << "依次输出顺序表的元素:" << endl;
	for (i = 0; i < s->top+1; i++)
	{
		cout << s->data[i]<<' ';     //遍历顺序表,并打印在控制台上
	}
}


int main()
{
	SqStack* s;
	ElemType x; 
	ElemType u;
	int k;
	s = InitSqStack();                                   //栈的初始化
	if (s == 0)
	{
		cout << "顺序栈初始化失败" << endl;
	}
	else
	{
		cout << "顺序栈初始化成功" << endl;
		AssignStack(s);                                //栈值的输入
		OputSqlist(s);                                 //栈值打印
		cout << endl;
		cout << "请输入需要入栈的元素:" << endl;
		cin >> x;
		k = Push(s, x);                                  //新栈值,入栈
		if (k == 0)
		{
			cout << "空间已经满了,无法压栈" << endl;
		}
		else
		{
			cout << "入栈成功" << endl;
			OputSqlist(s);
			delepop(s, &u);                   //栈顶值,出栈
			OputSqlist(s);
		}
		
	}
	return 0;
}

(2).链栈的入栈与出栈(这里的内容,基本与基本链表差不多,所以注释先不写了,只不过上一期用的是尾插法,而链栈用的是头插法的思路,很简单的)

在这里插入代码片:
#include <iostream>
using namespace std;

#define OK 1
#define ERR 0
typedef int Elemtype;
typedef struct SNode
{
	Elemtype data;
	struct SNode* next;
}Linklist;

Linklist *CreatNode()
{
	Linklist* S;
	S = (Linklist*)malloc(sizeof(Linklist));
	S->next = NULL;
	return S;
}

int StackEmpty(Linklist* S)
{
	if (!S->next)
	{
		cout << "链栈为空" << endl;
		return OK;
	}
	else
	{
		cout << "链栈不为空" << endl;
		return ERR;
	}
}

void InserStack(Linklist* S)
{
	Linklist* p;
	char flag = 'y';
	cout << "获取空间成功" << endl;
	while (flag == 'y' || flag == 'Y')
	{
		p = (Linklist*)malloc(sizeof(Linklist));
		cout << "请输入需要入栈的元素" << endl;
		cin >> p->data;
		p->next = S->next;
		S->next = p;
		getchar();
		cout << "请问还需要继续输入吗?(摁下 'y'或者‘Y’)" << endl;
		cin >> flag;
	}

}

int PushStack(Linklist* S, Elemtype x)
{
	Linklist* p;
	p = (Linklist*)malloc(sizeof(Linklist));
	if (!p)
	{
		return ERR;
	}
	p->data = x;
	p->next = S->next;
	S->next = p;
}

int Popstack(Linklist* S, Elemtype *x)
{
	Linklist* p;
	if (StackEmpty(S))
	{
		return ERR;
	}
	p = S->next;
	S->next = p->next;
	(*x) = p->data;
	free(p);
	return OK;
}

void OutputNode(Linklist* S)
{
	Linklist* p;
	int i;
	p = S->next;
	while (p != NULL)
	{
		cout << p->data<<" ";
		p = p->next;
	}
}


int main()
{
	Linklist* S = CreatNode();
	Elemtype k,u;
	StackEmpty(S);
	InserStack(S);
	cout << "栈中的元素是:"<< endl;
	OutputNode(S);
	cout << endl;
	cout << "请输入在栈顶插入的元素:" << endl;
	cin >> k;
	PushStack(S, k);
	cout << "栈中的元素是:" << endl;
	OutputNode(S);
	cout << endl;
	cout << "栈顶出栈的显示:" << endl;
	Popstack(S,&u);
	cout << endl;
	cout << "栈中的元素是:" << endl;
	OutputNode(S);
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The endeavor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值