嘉明的数据结构学习Day5——作栈和队列以及它们的顺序存储与链式存储的实现

栈和队列是两种特殊的线性表,栈遵循LIFO(后进先出)原则,仅允许在一端进行插入和删除;队列遵循FIFO(先进先出)原则,一端插入,另一端删除。文章详细介绍了栈的顺序实现和链式实现,包括初始化、入栈、出栈等操作,并给出了相应的C语言代码示例。同时,提到了队列的基本操作和应用场景。
摘要由CSDN通过智能技术生成

栈与队列是什么

栈和队列其实就是操作受限制的线性表。
下面来复习一下线性表的概念
具有n个相同类型元素的有限序列

有的人就会问,那么它们受限在哪里呢?
:只允许一段插入和删除。
队列:只允许一端插入一端删除。

前面说了栈是一种受限的线性表,因为它只允许插入和删除操作都在一端进行。
栈的专业术语
栈顶:即允许插入和删除的一端
栈底:即不允许删除和插入的一端
空栈:栈中不包含任何元素
LIFO后进先出 or FILO先进后出
例子:弹夹、烤串

栈的基本操作

初始化空栈栈
判断是否为空栈
出栈
入栈
读取栈顶元素

顺序栈的实现

顺序栈其实就是顺序表的简化版,它只可以在一端插入和删除。代码和顺序表其实大致相同
在这里插入图片描述

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

#define Maxsize 50

typedef int Elemtype;

typedef struct {
	Elemtype data[Maxsize];
	int top;
}sqStack;

//初始化栈
void InitStack(sqStack& s) {
	s.top = -1;
}

//判断栈是否为空(因为只是读取栈里面的元素,所以不用&)
bool IsEmpty(sqStack s) {
	if (s.top == -1) {
		return false;
	}
	return true;
}

//判断栈是否为满
bool IsFull(sqStack s) {
	if (s.top == Maxsize - 1) {
		return false;
	}
	return true;
}

//入栈
bool Push(sqStack& s,Elemtype x) {
	//判断栈是否为满
	if (IsFull(s)) {
		//x是要插入的元素
		s.data[++s.top] = x;
	}
	return true;
}

//出栈(因为x的需要改变,所以要加&)
bool Pop(sqStack& s,int &x) {
	//s是栈,x是出栈的元素
	//判断栈是否为空
	if (IsEmpty(s)) {
		//x是出栈的元素
		x = s.data[s.top--];
	}
	return true;
}

//输出栈
void printfStack(sqStack& s) {
	for (int i = 0; i <= s.top; i++) {
		printf("%d", s.data[i]);
	}
	printf("\n");
}

//读取栈顶元素
int top(sqStack s,int& x) {
	//判断栈是否为满
	if (IsEmpty(s)) {
		//x是出栈的元素
		x = s.data[s.top];
	}
	return x;
}

int main() {
	sqStack s;
	InitStack(s);
	Elemtype x;
	scanf("%d", &x);
	while (x != 9999) {
		Push(s, x);
		scanf("%d", &x);
	}
	printfStack(s);
	int p;
	Pop(s,p);
	printfStack(s);
	printf("出栈元素为:%d\n",p);
	printf("栈顶元素为:%d\n", top(s,p));
}

在这里插入图片描述

栈的链式实现

其实栈的链式存储其实就是只有头插法的链表,不过在删除上面只可以删除链表的表头指向的下一个元素
在这里插入图片描述

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

typedef int ElemType;
//定义链表的结点,链表中逻辑相邻的两个元素物理位置不相邻
typedef struct LNode {
	ElemType data;//数据域
	struct LNode* next;//指针域
}LNode, * LinkList;//别名


//头插法,即从头结点后面插入。比如输入的是12345,插入之后可能顺序就是54321
//也就是进栈的方式
LinkList creatList_Head(LinkList& L) {
	LNode* s;//定义要插入的指针
	int x;//定义需要插入的数据域
	L = (LinkList)malloc(sizeof(LNode));//头结点,没有数据域(默认值)。用于表明这是指针
	L->next = NULL;//因为头结点的指向下一个结点,但是还没定义所以是NULL
	scanf("%d", &x);
	//使用9999作为中止循环的结束符
	while (x != 9999) {
		s = (LinkList)malloc(sizeof(LNode));//申请空间创建新的结点
		s->data = x;//把数据赋值给插入结点的数据域
		s->next = L->next;//把指针指向的下一个结点赋给插入的结点的指针(头插法)
		L->next = s;//然后再把指针指向的结点指向插入的结点
		scanf("%d", &x);//再次读取数据知道x等于9999为止
	}
	return L;
}

//入栈操作(跟头插法一样)
bool Push(LinkList L,ElemType x){
	//因为链表的结点可以不断的加,所以这里没有限制条件
	LinkList s = (LinkList)malloc(sizeof(LNode));
	s->data = x;
	s->next = L->next;
	L->next = s;
	return true;
}

//出栈操作
bool Pop(LinkList L, int& x) {
	//获取头结点的下一个位置只在这里操作
	LinkList s = L->next;
	//判断是否为空栈
	if (s != NULL) {
		x = s->data;
		L->next = s->next; 
		free(s);
		s->next = NULL;
	}
	return true;
}

void PrintfStack(LinkList L) {
	LinkList s;
	s = L->next;
	while (s!= NULL) {
		printf("%d", s->data);
		s = s->next;
	}
	printf("\n");
}

void GetTop(LinkList L) {
	LinkList top = L->next;
	printf("栈顶元素为:%d\n", top->data);
}
int main() {
	LinkList St;
	creatList_Head(St);
	//入栈
	printf("入栈\n");
	Push(St, 5);
	printf("入栈后的栈:");
	PrintfStack(St);
	//出栈
	printf("出栈\n");
	int x;
	Pop(St, x);
	printf("出栈元素为:%d\n", x);
	printf("出栈后的栈:");
	PrintfStack(St);
	//获取栈顶元素
	GetTop(St);
}

在这里插入图片描述

队列

队列也是一种受限的线性表,它只允许一端进行插入操作、另一端进行删除操作。

队列的专业术语
队头:允许删除的一端
队尾:允许插入的一端
空队列:队列中无任何元素
FIFO先进先出 or LILO后进后出
例子:告诉公路的收费站、饭堂排队

队列的操作

初始化队列
判断是否为空队列
出队
入队
读取队头元素

队列的顺序存储

队列的链式存储

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值