【数据结构】——栈和队列

news2024/11/19 18:37:04

目录

1.栈

1.1栈的概念及结构

1.2栈的实现

1.2.1具体实现

Stack.h

栈初始化

栈销毁

入栈

出栈

取栈顶数据

判空

栈中有效元素的个数

全部Stack.c的代码

测试Test.c代码

2.队列

2.1队列的概念及结构

2.2队列的实现

Queue.h

队列初始化

队列销毁

队尾入队列(尾插)

队头出队列(头删 )

获取队头元素

获取队尾元素

判空

获取队列有效元素个数

完整的Queue.c代码

测试代码Test.c 


1.栈

1.1栈的概念及结构

栈:一种特殊的线性表,它只允许在固定的一端(栈顶

1.2 栈的实现
栈的实现一般可以使用 数组或者链表实现 ,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的
代价比较小。

)进行插入和删除元素的操作。进行插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵循后进先出(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈 ,入数据在栈顶。
出栈:栈的删除操作叫做出栈。 出数据也在栈顶

1.2栈的实现

栈的实现一般可以使用 数组或者链表实现 相对而言 数组的结构实现更优一些 。因为数组在尾上插
入数据的代价比较小。

1.2.1具体实现

Stack.h

从如下的几个方面实现栈的功能,看代码。

#pragma once

#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int STDatatype;
typedef struct Stack//栈
{
	STDatatype* a;
	int capacity;
	int top;   // 初始为0,表示栈顶位置下一个位置的下标
}ST;

//栈初始化
void StackInit(ST* ps);
//栈销毁
void StackDestroy(ST* ps);
//压栈,入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//取栈顶数据
STDatatype StackTop(ST* ps);
//判空
bool StackEmpty(ST* ps);
//栈中有效元素个数
int StackSize(ST* ps);

栈初始化

void StackInit(ST* ps)
{
	assert(ps);

	//方法1
	//ps->a = NULL;
	//ps->top = 0;
	//ps->capacity = 0;


	//方法2
	ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	ps->top = 0;
	ps->capacity = 4;
}

栈销毁

void StackDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

入栈

也及时要在栈顶放入数据

分析图如下:

void StackPush(ST* ps, STDatatype x)
{
	assert(ps);

	// 扩容
	if (ps->top == ps->capacity)
	{
		STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}

	//先放数据,top再++
	ps->a[ps->top] = x;
	ps->top++;
}

出栈

void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	ps->top--;
}

取栈顶数据

STDatatype StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->a[ps->top - 1];
}

判空

bool StackEmpty(ST* ps)
{
	assert(ps);

	/*if (ps->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/

	return ps->top == 0;
}

栈中有效元素的个数

int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

全部Stack.c的代码

void StackInit(ST* ps)
{
	assert(ps);

	//ps->a = NULL;
	//ps->top = 0;
	//ps->capacity = 0;

	ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	ps->top = 0;
	ps->capacity = 4;
}

void StackDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

void StackPush(ST* ps, STDatatype x)
{
	assert(ps);

	// 扩容
	if (ps->top == ps->capacity)
	{
		STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity *= 2;
	}

	//先放数据,top再++
	ps->a[ps->top] = x;
	ps->top++;
}

// 
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	ps->top--;
}

STDatatype StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->a[ps->top - 1];
}

bool StackEmpty(ST* ps)
{
	assert(ps);

	/*if (ps->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/

	return ps->top == 0;
}

int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

测试Test.c代码

#include "Stack.h"

void TestStack1()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	StackPush(&st, 5);

	printf("size:%d\n", StackSize(&st)); // 不关心底层实现
	//printf("size:%d\n", st.top);  // 关心
	printf("size:%d\n", st.top + 1);  // 关心


	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	//StackPop(&st);
	//printf("%d\n", StackTop(&st));

	StackDestroy(&st);
}

int main()
{
	TestStack1();

	return 0;
}

2.队列

2.1队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。

队列具有先进先出 FIFO(First In First Out)

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

 PS:队列和栈几乎是相反的。

2.2队列的实现

实现队列更适合选择用单链表,而不是用数组,数组不适合头插尾插,效率低。 

Queue.h

#pragma once
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int QDataType;
//链式结构:表示队列
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;
//队列的结构
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;
//队列初始化
void QueueInit(Queue* pq);
//队列销毁
void QueueDestroy(Queue* pq);
//队尾入队列
void QueuePush(Queue* pq, QDataType x);
//队头出队列
void QueuePop(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取队列有效元素个数
int QueueSize(Queue* pq);

队列初始化

void QueueInit(Queue* pq)
{
	assert(pq);

	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

队列销毁

void QueueDestroy(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;

		free(del);
		//del = NULL;
	}

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

队尾入队列(尾插)

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	newnode->data = x;
	newnode->next = NULL;

	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}

	pq->size++;
}

队头出队列(头删 )

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* del = pq->head;
		pq->head = pq->head->next;

		free(del);
	}

	pq->size--;
}

获取队头元素

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

获取队尾元素

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

判空

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL && pq->tail == NULL;
}

获取队列有效元素个数

int QueueSize(Queue* pq)
{
	assert(pq);


	//方法1
	/*int size = 0;
	QNode* cur = pq->head;
	while (cur)
	{
		cur = cur->next;
		++size;
	}

	return size;*/


	//方法2
	return pq->size;
}

完整的Queue.c代码

#include "Queue.h"

void QueueInit(Queue* pq)
{
	assert(pq);

	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;

		free(del);
		//del = NULL;
	}

	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	newnode->data = x;
	newnode->next = NULL;

	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}

	pq->size++;
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* del = pq->head;
		pq->head = pq->head->next;

		free(del);
	}

	pq->size--;
}

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL && pq->tail == NULL;
}

// 1G = 1024MB
// 1024MB = 1024*1024KB
// 1024*1024KB = 1024*1024*1024Byte

int QueueSize(Queue* pq)
{
	assert(pq);


	//方法1
	/*int size = 0;
	QNode* cur = pq->head;
	while (cur)
	{
		cur = cur->next;
		++size;
	}

	return size;*/


	//方法2
	return pq->size;
}

测试代码Test.c 

#include "Queue.h"



void TestQueue()
{
	//Queue q1;
	//Queue q2;
	//QueueInit(&q1);
	//QueueInit(&q2);


	//QueueDestroy(&q1);
	//QueueDestroy(&q2);

	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);

	printf("%d ", QueueFront(&q));
	QueuePop(&q);

	QueuePush(&q, 3);
	QueuePush(&q, 4);

	printf("%d\n", QueueSize(&q));
	printf("%d\n", QueueEmpty(&q));
	printf("%d\n", QueueFront(&q));
	printf("%d\n", QueueBack(&q));

	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");

	printf("%d\n", QueueSize(&q));
	printf("%d\n", QueueEmpty(&q));
	//printf("%d\n", QueueFront(&q));
	//printf("%d\n", QueueBack(&q));

	QueueDestroy(&q);
}

int main()
{
	//TestStack1();
	TestQueue();

	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/82092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat8.0使用tomcat-redis-session-manager共享session【开源】,tomcat实现session共享

前言 【可跳过&#xff0c;比较简单】 由于以前的项目配置了多个tomcat服务使用了nginx代理&#xff0c;但是关闭某个tomcat的时候登录用户信息丢失&#xff0c;用户得重新登录&#xff0c;这就让人体验不好了&#xff1b;我们可以复制各个tomcat服务的session来实现的sessio…

【供给需求优化算法】基于适应度-距离-平衡供给需求优化算法FDB-SDO附matlab代码

​✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法…

毕设选题推荐基于python的django框架的学生课程管理系统

&#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设老哥&#x1f525; &#x1f496; 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; Java实战项目专栏 Python实…

前端二面常见手写面试题(必备)

用正则写一个根据name获取cookie中的值的方法 function getCookie(name) {var match document.cookie.match(new RegExp((^| ) name ([^;]*)));if (match) return unescape(match[2]); }获取页面上的cookie可以使用 document.cookie 这里获取到的是类似于这样的字符串&…

新一代推理部署工具FastDeploy与十大硬件公司联合打造:产业级AI模型部署实战课...

人工智能产业应用发展的越来越快&#xff0c;开发者需要面对的适配部署工作也越来越复杂。层出不穷的算法模型、各种架构的AI硬件、不同场景的部署需求、不同操作系统和开发语言&#xff0c;为AI开发者项目落地带来极大的挑战。为了解决AI部署落地难题&#xff0c;我们发布了新…

(附源码)springboot校园跳蚤市场 毕业设计 646515

基于Springboot校园跳蚤市场 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。现代社会越来…

Python解题 - CSDN周赛第14期 - 单词编码

本期其实没啥好写的&#xff0c;都是数学题&#xff0c;和算法关系不大&#xff0c;唯手熟尔。而且又出现了同一天的每日一练中包含了赛题&#xff0c;这算不算官方泄题呢&#xff1f;看来下次在竞赛之前先做完每日一练大有益处呢。 第一题&#xff1a;字符串全排列 对K个不同字…

算法leetcode|21. 合并两个有序链表(rust重拳出击)

文章目录21. 合并两个有序链表&#xff1a;样例 1&#xff1a;样例 2&#xff1a;样例 3&#xff1a;提示&#xff1a;原题传送门&#xff1a;分析&#xff1a;题解&#xff1a;rustgoccpythonjava21. 合并两个有序链表&#xff1a; 将两个升序链表合并为一个新的 升序 链表并…

一款基于SpringBoot+layui 开源的固定设备资产管理系统源码 源码免费分享

淘源码&#xff1a;国内专业的免费源码下载平台 分享一款开源的固定设备资产管理系统源码&#xff0c;系统可对常用资产设备进行信息化管理&#xff0c;包含自定义支持各类设备、自带导入导出、维护工作统计、采购管理、文档管理、合同管理等功能&#xff0c;包含对资产的登记、…

如何优雅的设计和使用缓存?

背景 在之前的文章中你应该知道的缓存进化史介绍了爱奇艺的缓存架构和缓存的进化历史。俗话说得好&#xff0c;工欲善其事&#xff0c;必先利其器&#xff0c;有了好的工具肯定得知道如何用好这些工具&#xff0c;本篇将介绍如何利用好缓存。 1.确认是否需要缓存 在使用缓存…

CentOS7 修改ip、MAC、UUID

对于复制的虚拟机&#xff0c;在开机时&#xff0c;VMware自动为其分配了相同的Mac地址以及IP地址(除IP地址是dhcp自动获取外) UUID&#xff08;Universally Unique Identifier&#xff09;是系统层面的全局唯一标识符号&#xff0c;Mac地址以及IP地址是网络层面的标识号 两台不…

dtb如何转换到platform_device

分2步&#xff0c;第一步是首先转换为device_node&#xff0c;第二步device_node转换为platform_device。 第一步 /*** unflatten_device_tree - create tree of device_nodes from flat blob** unflattens the device-tree passed by the firmware, creating the* tree of st…

mysql常用索引

1.普通索引 navicat中为NORMAL 语句为 ADD INDEX //采用普通索引的方式可以大大提高数据库的工作效率 2.唯一索引 navicat中为NORMAL 语句为 ADD UNIQUE INDEX //采用唯一索引的方式可以大大提高数据库的工作效率、并且数据无重复 3.主键索引 navicat中为主键 语句为 AD…

ALSA系统简析

一 音频架构 如图所示 是 嵌入式系统的音频连接 音频编解码器将数字音频信号 转换成 扬声器播放所需要的模拟声音信号。而通过麦克风时&#xff0c;则执行相反的过程。 数字音频信号通过 PCM技术对模拟信号以某个比特率采样得到的&#xff0c;编解码器的任务就是以支持的PCM…

非零基础自学计算机操作系统 第1章 操作系统概述 1.4 操作系统的分类 1.4.1 多道批处理操作系统 1.4.2 分时操作系统

非零基础自学计算机操作系统 文章目录非零基础自学计算机操作系统第1章 操作系统概述1.4 操作系统的分类1.4.1 多道批处理操作系统1.4.2 分时操作系统第1章 操作系统概述 1.4 操作系统的分类 按照操作系统的功能可将其分为以下几类&#xff1a;多道批处理操作系统、分时操作系…

力扣(LeetCode)143. 重排链表(C++)

模拟 五步做完 : ①遍历链表&#xff0c;得到链表长度 ②找到中间结点 ③反转链表后半段的结点指向 ④重排链表 ⑤尾结点的指向置空 初始链表 L0→L1→…→Ln−1→LnL0 → L1 → … → Ln - 1 → LnL0→L1→…→Ln−1→Ln 重排链表 L0→Ln→L1→Ln−1→L2→Ln−2→…L0 → Ln…

MongoDB数据库 —— 图形化工具

在前面通过使用MongoDB在命令窗口操作数据库&#xff0c;而MySQL数据库也同样可以在命令窗口使用sql语句操作数据库&#xff0c;在安装数据库的时候提到可以安装这个图形化工具的&#xff0c;为了节省安装时间和卡顿选择后续安装MongoDB图形化工具&#xff0c;在MySQL数据中同样…

[附源码]JAVA毕业设计疫情防控期间人员档案追演示录像上(系统+LW)

[附源码]JAVA毕业设计疫情防控期间人员档案追演示录像上&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#x…

Spring Cloud Zuul网关的介绍及使用

Zuul 是 Netflix OSS 中的一员&#xff0c;是一个基于 JVM 路由和服务端的负载均衡器。提供路由、监控、弹性、安全等方面的服务框架。Zuul 能够与 Eureka、Ribbon、Hystrix 等组件配合使用。 Zuul 的核心是过滤器&#xff0c;通过这些过滤器我们可以扩展出很多功能&#xff0…

猿如意中的【Linux命令查询】工具详情介绍

一、工具名称 Linux命令查询 二、下载安装渠道 Linux命令查询通过CSDN官方开发的【猿如意】客户端进行下载安装。 2.1 什么是猿如意&#xff1f; 猿如意是一款面向开发者的辅助开发工具箱&#xff0c;包含了效率工具、开发工具下载&#xff0c;教程文档&#xff0c;代码片段…