当前位置: 首页 > news >正文

数据结构 04

4. 栈

4.2. 链式栈

4.2.1. 特性

逻辑结构:线性结构
存储结构:链式存储结构
操作:创建,入栈,出栈,清空,获取

4.2.2. 代码实现

头文件 LinkStack.h

#ifndef __LINKSTACK_H__
#define __LINKSTACK_H__
typedef int datatype;
typedef struct linkstack
{
   datatype data;
   struct linkstack *next;
} linkstack_t;
//1.创建一个空的栈
void createEmptyLinkStack(linkstack_t **ptop);
//2.入栈,ptop是传入的栈针的地址,data是入栈的数据
int pushLinkStack(linkstack_t **ptop, datatype data);
//3.判断栈是否为空
int isEmptyLinkStack(linkstack_t *top);
//4.出栈
datatype popLinkStack(linkstack_t **ptop);
//5.清空栈
void clearLinkStack(linkstack_t **ptop);
//6.求栈的长度
int lengthLinkStack(linkstack_t *top);
//7.获取栈顶数据,不是出栈,不需要移动main函数中的top,所以用一级指针
datatype getTopLinkStack(linkstack_t *top);
#endif

1.创建一个空的栈

void createEmptyLinkStack(linkstack_t **ptop)
{
	*ptop = NULL;
}
  1. 入栈
int pushLinkStack(linkstack_t **ptop, datatype data)
{
	// 定义一个指针pnew,指向新节点
	linkstack_t *pnew = (linkstack_t *)malloc(sizeof(linkstack_t));
	if(pnew == NULL)
	{
		printf("New Node Creation Failed!!\n");
		return -1;
	}
	// 初始化
	pnew->data = data;
	pnew->next = *ptop;	// 新节点的指针域,指向旧节点的地址
	// 栈针移动到最新的节点
	*ptop = pnew;
}
  1. 判断栈是否为空
int isEmptyLinkStack(linkstack_t *top)
{
	// 栈针指向NULL时,栈为空
	return top == NULL;
}
  1. 出栈
datatype popLinkStack(linkstack_t **ptop)
{
	// 容错判断
	if (isEmptyLinkStack)
	{
		printf("Stack is empty!!\n");
		return NULL;
	}
	// 定义指针pdel,指向出栈节点
	linkstack_t* pdel = NULL;
	// 定义中间变量,暂存出栈数据
	datatype data = 0;
	// pdel指向出栈节点
	pdel = *ptop;
	// data暂存出栈数据
	data = pdel->data;
	// 栈针移动,释放出栈节点
	*ptop = (*ptop)->next;
	free(pdel);
	pdel = NULL;
	// 返回出栈数据
	return data;
}
  1. 清空栈
void clearLinkStack(linkstack_t **ptop)
{
	while(!isEmptyLinkStack(*ptop))
	{
		popLinkStack(ptop);
	}
}
  1. 求栈的长度
int lengthLinkStack(linkstack_t *top)
{
	// 定义一个变量,作为长度的计数
	int len = 0;
	// 链式栈长度的计算实际上是无头单向链表的遍历问题
	while(top =  NULL)
	{
		len ++;	// 累计计数
		top = top->next;	// 栈针移动
	}
}
  1. 获取栈顶数据
datatype getTopLinkStack(linkstack_t *top)
{
	// 容错判断
	if (!isEmptyLinkStack(top))
	{
		printf("Stack is empty\n");
		return -1;
	}
	// 返回栈顶数据
		return top->data;
}

5. 队列

5.1. 特性

  1. 一端只能输入,称为队尾;另一端只能输出,称为队头
  2. 先进先出:FIFO
  3. 存在假溢出现象:
    1)当数据存满后,有数据从队头出列后,应该可以存入新的数据,但是因为数据在队列里面不移动,所以队尾不存在空位,新数据无法入列,但是队列未满,如下图
    假溢出现象
    2)解决方法:顺序队列

5.2. 顺序队列(循环队列)

循环队列
需要实现头和尾都可以走完最后一位之后再走回来,比如4->5->0->1。
方法一:

if(i==N)
	i = 0;
else
	i++;

方法二:

i = (i+1)%N;

5.2.1. 代码实现

头文件 sequeue.h

#ifndef __SEQUEUE_H__
#define __SEQUEUE_H__
#define N 6
typedef int datatype;
typedef struct
{
	datatype data[N];//循环队列的数组
	int rear;//存数据端 rear 后面
	int front;//取数据端 front 前面
}sequeue_t;

// 1. 创建一个空的队列
sequeue_t *createEmptySequeue();
// 2. 判断队列是否为满
int isFullSequeue(sequeue_t *p);
// 3. 入列 data代表入列的数据
int inSequeue(sequeue_t *p,datatype data);
// 4. 判断队列是否为空
int isEmptySequeue(sequeue_t *p);
// 5. 出列 
datatype outSequeue(sequeue_t *p);
// 6. 求队列的长度
int lengthSequeue(sequeue_t *p);
// 7. 清空队列函数
void clearSequeue(sequeue_t *p);
#endif
  1. 创建一个空队列
sequeue_t *createEmptySequeue()
{
	// 申请空间存放队列结构
	sequeue_t *p = (sequeue_t *)malloc(sizeof(sequeue_t));
	if(p == NULL)
	{
		printf("Space opening failure !!\n");
		return NULL;
	}
	// 初始化
	p->rear = 0;
	p->front = 0;

	return p;
}
  1. 判断是否为满
int isFullSequeue(sequeue_t *p)
{
	// 循环队列的判满公式
	return p->front == (p->rear + 1) % N;
}
  1. 入列
int inSequeue(sequeue_t *p, datatype data)
{
	// 容错判断
	if( isFullSequeue(p) )
	{
		printf("Space is Full !!\n");
		return -1;
	}
	// 入列
	p->data[p->rear] = data;
	// 队尾向后移动一个数据单位
	p->rear = (p->rear + 1) % N;
	return 0;
}
  1. 判断是否为空
int isEmptySequeue(sequeue_t *p)
{
	// 空返回1,非空返回0
	return p->rear == p->front;
}
  1. 出列
datatype outSequeue(sequeue_t *p)
{
	// 容错判断
	if ( isEmptySequeue(p) )
	{
		printf("Space is empty !!\n");
		return -1;
	}
	// 出列
		// 1)定义一个变量,暂存出列数据
	datatype data = p->data[p->front];
		// 2)队头移动
	p->front = (p->front + 1) % N;
	
	return data;
}
  1. 求队列的长度
int lengthSequeue(sequeue_t *p)
{
	// 队尾可以大于队头,也可以小于队头
	// rear >= front, rear - front 是长度
	// rear < front, rear + N -front ,这种情况相当于,队尾套了队头一圈
	// 两种情况综合之后得到公式 ( rear + N - front ) % N
	return ( p->rear - p->front + N ) % N;
}

+N 之后 %N 对结果来说,相当于没操作

  1. 清空队列函数
void clearSequeue(sequeue_t *p)
{
	// p->front = p->rear;	// 不返回数据
	while(!isEmptySequeue(p))
		outSequeue(p);	// 可以返回出列数据, 看需求
}

相关文章:

  • 100.16 AI量化面试题:监督学习技术在量化金融中的应用方案
  • C#/.NET/.NET Core技术前沿周刊 | 第 24 期(2025年1.27-1.31)
  • SpringMVC父子容器:Web应用架构的隐形守护者
  • 回归新系列——网络安全实操干货系列——Kali Linux新版本——Kali Purple实操指南——信息收集篇1——Nmap(其一)
  • pptx文档提取信息
  • 20vue3实战-----使用echarts搭建各种图表
  • Java 大视界 -- 全球数据治理格局下 Java 大数据的发展路径(89)
  • spring和mybatis的整合
  • Python的那些事第二十二篇:基于 Python 的 Django 框架在 Web 开发中的应用研究
  • sort快排
  • 包管理器-汇总介绍
  • 数据结构 day 07
  • 性格测评小程序06用户注册校验
  • PHP框架入门指南:从零构建现代Web应用
  • 中上211硕对嵌入式AI感兴趣,如何有效规划学习路径?
  • SpringMVC 请求参数接收
  • Unity-New Input System
  • 2-安装YIUI
  • AI语言模型的技术之争:DeepSeek与ChatGPT的架构与训练揭秘
  • 5G与物联网的协同发展:打造智能城市的未来
  • 网络直播间销售玩具盲盒被指侵权,法院以侵犯著作权罪追责
  • 三星“七天机”质保期内屏幕漏液被拒保,澎湃介入后已解决
  • 女子应聘文员被说“太丑”?官方回应:有关部门启动核查处置
  • 上博东馆常设陈列入选全国博物馆“十大精品”
  • 国防部:赖清德歪曲二战历史,背叛民族令人不齿
  • 中国证券业协会修订发布《证券纠纷调解规则》