03-数据结构-栈与队列

news2024/11/23 10:00:52

1.栈

77a8072800534dd1b6072ce98752205d.png

栈和队列是两种操作受限的线性表。如上图所示显示栈的结构

栈:先进后出,入栈(数据进入) 和出栈(数据出去)均在栈顶操作。

常见栈的应用场景包括括号问题的求解,表达式的转换和求值,函数调用和递归实现

1.1 栈的代码实现

#include<iostream>
#include<stdio.h>
#include<malloc.h>
#include<assert.h>

typedef int STDataType;
typedef struct node
{
	STDataType x;
	struct node* next;
}node;
typedef struct Stack
{
	node* head;
	int nums;		// 长度
}Stack;

// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->head = NULL;
	ps->nums = 0;
}

// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	node* new_node = (node*)malloc(sizeof(node));
	new_node->x = data;
	new_node->next = ps->head;
	ps->head = new_node;
	ps->nums++;
}

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->nums == 0;
}

// 出栈 
STDataType StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	STDataType ret = ps->head->x;
	node* del = ps->head;
	ps->head = ps->head->next;
	free(del);
	ps->nums--;
	return ret;
}

// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->nums;
}

// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);
	node* tmp = ps->head;
	while (tmp)
	{
		ps->head = ps->head->next;
		free(tmp);
		tmp = ps->head;
	}
	ps->head = NULL;
	ps->nums = 0;
}

int main()
{
	Stack sta;
	StackInit(&sta);
	StackPush(&sta, 1);
	StackPush(&sta, 2);
	StackPush(&sta, 3);
	StackPush(&sta, 4);
	StackPush(&sta, 5);
	std::cout << StackSize(&sta) << std::endl;
	while (!StackEmpty(&sta))
	{
		printf("%d\n", StackPop(&sta));
	}
}

1.2 进制转化

#include <iostream>
#include <malloc.h>

using namespace std;

/**** 结 构 体 声 明 ****/
typedef struct scStack{
    struct scStack *next;
    int elem;
}scStack;

/*
    余数入栈
*/
scStack *push(scStack *stack,int elem){
    scStack *newStack = (scStack *)malloc(sizeof(scStack));
    newStack->elem = elem;
    newStack->next = stack;
    stack = newStack;
    return stack;
}

/*
    进制转换
*/
scStack *sysConvert(int num,int system,scStack *sys){
    while(num > 0){
        sys = push(sys,num % system);
        num /= system;
    }
    return sys;   //返回栈顶
}

/*
   余数出栈
*/
void pop(scStack *stack){
    while(stack){
        scStack *top = stack;
        top->elem >= 10 ? printf("%c",top->elem + 'a' - 10) : printf("%d",top->elem);
        stack = stack->next;
        free(top);
    }
    cout<<endl<<"转换完毕!"<<endl;
}

/*
    主函数
*/
int main(){
    scStack *stack = NULL; //初始化栈
    int num,system;
    cout<<"请输入一个10进制数:";
    cin>>num;
    cout<<"请输入想要转换为多少进制:";
    cin>>system;
    stack = sysConvert(num,system,stack);
    pop(stack);
    return 0;
}

1.3 括号匹配

#include<stdio.h>

#define MaxSize 10

typedef struct {    // 定义顺序栈
    int data[MaxSize];  // 静态数组存放栈中元素
    int top;    // 栈顶指针:指向目前栈顶元素的位置
} SeqStack;

void InitStack(SeqStack &S) {
    S.top = -1;
}

bool StackEmpty(SeqStack S) {
    if(S.top == -1) {
        return true;
    } else {
        return false;
    }
}

bool Push(SeqStack &S, char x) {
    if(S.top == MaxSize - 1) {
        return false;
    }
    S.top = S.top + 1;
    S.data[S.top] = x;
    return true;
}

bool Pop(SeqStack &S, char &x) {
    if(S.top == -1) {
        return false;
    }
    x = S.data[S.top];
    S.top = S.top - 1;
    return true;
}

bool bracketCheck(char str[], int length) {
    SeqStack S;
    InitStack(S);
    for(int i = 0;i < length;i++) {
        if(str[i] == '(' || str[i] == '[' || str[i] == '{') {
            Push(S, str[i]);
        } else {
            if(StackEmpty(S)) {
                return false;
            }
            char topElem;
            Pop(S, topElem);
            if(str[i] == ')' && topElem != '(') {
                return false;
            }
            if(str[i] == ']' && topElem != '[') {
                return false;
            }
            if(str[i] == '}' && topElem != '{') {
                return false;
            }
        }
    }
    return StackEmpty(S);
}

int main() {
    char A[] = "[([][])]";
    if(bracketCheck(A, 8)) {
        printf("A The match is successful\n");
    }
	else
	{
		printf("A The match is faild\n");
	}
	
	char B[] = "[([][]]";
    if(bracketCheck(B, 8)) {
        printf("B The match is successful\n");
    }
	else
	{
		printf("B The match is faild\n");
	}
}

1.4 递归

//X有n个盘子,从上到下有从小到大的顺序,有三个柱子X,Y, Z,把n个盘子从X移到Z,
//Y为辅助,并在移动过程中有一个约束条件就是大盘永远不能在小盘上面。
//
#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100

typedef int ElemType;//盘子的结构
typedef struct//柱子(栈)的结构
{
    char name;
    ElemType* base;
    ElemType* top;
}StackType;
 
int initstack(StackType* s,char name)
{
    s->name=name;
    s->base=(ElemType*)malloc(MAXSIZE*sizeof(ElemType));
    if(s->base==NULL)
        exit(0);
    s->top=s->base;
    return 1;
 
 
}
 
int push(StackType* s,ElemType e)
{
    if(s->top-s->base>=MAXSIZE)
        exit(0);
    *(s->top)=e;
    s->top++;
    return 1;
}
 
ElemType pop(StackType* s)
{
    if(s->top==s->base)
        exit(0);
    s->top--;
    return *(s->top);
}
 
int main()
{
    int all;
    int i;
    StackType X;
    StackType Y;
    StackType Z;
    initstack(&X,'X');
    initstack(&Y,'Y');
    initstack(&Z,'Z');
    while(1)
    {
    printf("请输入X柱子开始有多少个盘子\n");
    scanf("%d",&all);
    for(i=all;i>0;i--)
    {
        push(&X,i);
    }
    hannota(all,&X,&Y,&Z);
    }
 
 
    return 1;
}
 
int hannota(int n,StackType* x,StackType* y,StackType* z)
{
    if(1==n)
    {
        move(x,z);
        printf("from %c to %c\n",x->name,z->name);
        return 1;
    }
    hannota(n-1,x,z,y);//先解决n-1个盘子移到辅助柱子Y的汉洛塔问题
    move(x,z);//最后一个从x移到Z
    printf("from %c to %c\n",x->name,z->name);
    hannota(n-1,y,x,z);//解决n-1个盘子移到柱子z的汉洛塔问题
    return 1;
}
 
int move(StackType* s1,StackType* s2)
{
    ElemType temp;
    temp=pop(s1);
    push(s2,temp);
    return 1;
}

2.队列

队列的应用场景包括计算机系统中各种资源的管理,消息缓冲器的管理和广度优先搜索遍历等。

队列是先进先出,如上图所示,队列从队尾入队,从队头出队。队列有顺序队列,链队列和循环队列

2.1 链队列的代码实现

#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct DataNode
{	
	ElemType data;
	struct DataNode *next;
} DataNode;				//链队数据结点类型
typedef struct
{	
	DataNode *front;
	DataNode *rear;
} LinkQuNode;			//链队类型
void InitQueue(LinkQuNode *&q)
{	
	q=(LinkQuNode *)malloc(sizeof(LinkQuNode));
	q->front=q->rear=NULL;
}
void DestroyQueue(LinkQuNode *&q)
{
	DataNode *p=q->front,*r;//p指向队头数据结点
	if (p!=NULL)			//释放数据结点占用空间
	{	r=p->next;
		while (r!=NULL)
		{	free(p);
			p=r;r=p->next;
		}
	}
	free(p);
	free(q);				//释放链队结点占用空间
}
bool QueueEmpty(LinkQuNode *q)
{
	return(q->rear==NULL);
}
void enQueue(LinkQuNode *&q,ElemType e)
{	DataNode *p;
	p=(DataNode *)malloc(sizeof(DataNode));
	p->data=e;
	p->next=NULL;
	if (q->rear==NULL)		//若链队为空,则新结点是队首结点又是队尾结点
		q->front=q->rear=p;
	else
	{	q->rear->next=p;	//将p结点链到队尾,并将rear指向它
		q->rear=p;
	}
}
bool deQueue(LinkQuNode *&q,ElemType &e)
{	DataNode *t;
	if (q->rear==NULL)		//队列为空
		return false;
	t=q->front;				//t指向第一个数据结点
	if (q->front==q->rear)  //队列中只有一个结点时
		q->front=q->rear=NULL;
	else					//队列中有多个结点时
		q->front=q->front->next;
	e=t->data;
	free(t);
	return true;
}
int main()
{
	LinkQuNode *q;     //创建队列q  
	ElemType e;
	InitQueue(q);   //初始化队
	enQueue(q,'a');
	enQueue(q,'b');
	enQueue(q,'c'); //依次进队a,b,c
	deQueue(q,e);
	printf("%c\n",e);   //出队元素a 
	deQueue(q,e);
	printf("%c\n",e);  //出队元素b 
	deQueue(q,e);
	printf("%c\n",e);  //出队元素c
	DestroyQueue(q);  //销毁队 
	return 0; 
} 

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

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

相关文章

运维知识点-Kubernetes_K8s

Kubernetes RBAC配置不当攻击场景攻击过程 RBAC配置不当 Service Account本质是服务账号&#xff0c;是Pod连接K8s集群的凭证。 在默认情况下&#xff0c;系统会为创建的Pod提供一个默认的Service Account&#xff0c; 用户也可以自定义Service Account&#xff0c;与Service…

Postgresql中自增主键序列的使用以及数据传输时提示:错误:关系“xxx_xx_xx_seq“不存在

场景 Postgresql在Windows中使用pg_dump实现数据库(指定表)的导出与导入&#xff1a; Postgresql在Windows中使用pg_dump实现数据库(指定表)的导出与导入-CSDN博客 上面讲使用pg_dump进行postgresql的导出与导入。 如果使用Navicat可以直接连接两个库&#xff0c;则可直接使…

如何在安卓手机Termux上安装MariaDB(MySQL)并实现远程连接数据库

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

基于win安装的docker内安装sonar时启动时错误

elasticsearch exited with code 78 以下要求和建议适用于在生产中的Docker中运行Elasticearch。 将vm.max_map_count至少设置为262144要用于生产&#xff0c;必须将vm.max_map_count内核设置至少设置为262144。 如何设置vm.max_map_count取决于您的平台。 这对我来说就是&a…

easyrecovery2024免费手机版数据恢复软件下载

easyrecovery14是easyrecovery系列软件的新版本&#xff0c;也是目前行业领先的数据恢复软件&#xff0c;具备更快捷、更高效、更便捷三大特色&#xff0c;能够帮助用户轻松恢复电脑丢失的数据。目前软件支持恢复不同存储介质数据&#xff0c;包括硬盘、光盘、U盘/移动硬盘、数…

C++学习笔记——STL(标准模板库)

系列文章 http://t.csdnimg.cn/u80hL 目录 系列文章[TOC](目录) 比喻与理解1.比喻2. 理解string和STL的关系string类型的存在意义——集中实现符号信息的管理 STL1. 什么是STL2. SGI版本3. STL的六大组件 string类1. C语言中的字符串2. 标准库中的string类2.1 string类2.2 str…

linux命令速查表

这是一个linux常见命令的列表&#xff01; 相关学习资料&#xff1a;【收藏】Linux系统常用命令速查手册&#xff08;附PDF下载方式&#xff09;_linux命令大全详解pdf-CSDN博客文章浏览阅读651次。给大家收集整理了日常常用的Linux系统命令&#xff0c;仅供大家参考。大家如…

【ESP32填坑日记】问题篇⑧ VScode中提示无法使用compilerPath解析配置:“C:/xxx/xtensa-esp32-elf-gcc.exe“

关注星标公众号&#xff0c;不错过精彩内容 作者 | 量子君 微信公众号 | 极客工作室 问题描述 在编译成功&#xff0c;重启之后就编译不成功了&#xff0c;并报如图错误&#xff1a; 无法使用 compilerPath 解析配置&#xff1a;“C:/xxx/xtensa-esp32-elf-gcc.exe” 解决…

如何压缩PDF文件大小在5m以内?三个方法轻松搞定!

现在电子化阅读越来越广泛&#xff0c;我们会从网络上下载很多内存很大的电子书、PDF论文&#xff0c;放在电脑上也着实占用空间&#xff0c;如何把PDF压缩到最小&#xff0c;下面就向大家介绍3款好用的PDF压缩工具和具体的操作步骤。 工具一&#xff1a;使用嗨格式压缩大师软件…

opencv 入门二(播放视频)

环境配置如下&#xff1a; opencv 入门一&#xff08;显示一张图片&#xff09;-CSDN博客 用OpenCV播放视频就像显示图像一样简单。唯一不同的是&#xff0c;我们需要某种循环来读取视频序列中的每一帧。 源码如下&#xff1a; #include <iostream> #include <str…

基于Arduino的智能太阳能追光系统(论文+源码)

1. 系统设计 本次的设基于Arduino的智能太阳能追光系统的设计&#xff0c;整体结构如图2.1所示。整个系统包括Arduino开发板&#xff0c;按键模块&#xff0c;太阳能板&#xff0c;X轴电机,Y轴电机&#xff0c;电池充电模块&#xff0c;电源模块&#xff0c;四路光照检测模块等…

NVMe前世今生

NVMe前世今生 1 NVMe的由来2 NVMe工作原理3 NVMe优点4 NVMe适用场景 本文属于《 NVMe协议基础系列教程》之一&#xff0c;欢迎查看其它文章。 1 NVMe的由来 目前机械硬盘大多数使用 SATA (Serial ATA Advanced Host Controller Interface) 接口&#xff0c;接口协议为 AHCI&a…

C++报错:error C2238: 意外的标记位于“;”之前

报错信息如下&#xff1a; 编译遇见这样的错误信息主要有一下几种&#xff1a; 情况一&#xff1a; 多数情况下出现这种问题的原因是因为头文件重复包含&#xff1a;即头文件A包含了B&#xff0c;头文件B又包含了A&#xff0c;导致编译器在加载头文件时陷入死循环。 解决办法…

Spring核心原理理解与总结

Spring 核心原理理解与总结 Spring 基础 什么是 Spring 框架&#xff1f; Spring 是一款开源的轻量级 Java 开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。开箱即用。 一般说 Spring 框架指的都是 Spring Framework 核心功能主要是 IoC 和 AOP。 Sp…

python与机器学习2,激活函数

目录 1 什么是激活函数&#xff1f; activation function 1.1 阈值 1.2 激活函数a(x) &#xff0c;包含偏置值θ 1.3 激活函数a(x) &#xff0c;包含偏置值b 2 激活函数1: 单位阶跃函数 2.1 函数形式 2.2 函数图形 2.3 函数特点 2.4 代码实现这个 单位阶跃函数 3 激活…

羊大师提示,把工作和生活分开轻松拥有幸福人生

羊大师提示&#xff0c;把工作和生活分开轻松拥有幸福人生 工作对于每个人来说是必不可少的一部分&#xff0c;但是在忙碌的工作中也不能忘记了生活的美好。如何平衡好工作和生活&#xff0c;成为了许多人追求的目标。 我们都知道&#xff0c;工作和生活之间的平衡是非常重要…

【CSDN】CSDN 的简单使用与常用快捷键

【CSDN】CSDN 的简单使用与常用快捷键 1&#xff09;目录2&#xff09;标题3&#xff09;代码块4&#xff09;黑点标题5&#xff09;字体5.1.加粗5.2.标记5.3.颜色 6&#xff09;图片6.1.居中6.2.左对齐6.3.右对齐6.5.图片大小调整 1&#xff09;目录 创建标题目录快捷键&…

PFA微柱实验用同位素离子交换柱耐强酸碱

PFA同位素离子交换柱是一种常用于分离和富集同位素的柱子。离子交换柱的工作原理是通过固定的离子交换基质&#xff0c;将目标同位素离子与其他离子相互交换&#xff0c;从而实现分离的目的。 PFA同位素离子交换柱用于同位素的分析和测量。在样品中&#xff0c;不同同位素的离子…

hive企业级调优策略之小文件合并

测试所用到的数据参考&#xff1a; 原文链接&#xff1a;https://blog.csdn.net/m0_52606060/article/details/135080511 本教程的计算环境为Hive on MR。计算资源的调整主要包括Yarn和MR。 优化说明 小文件合并优化&#xff0c;分为两个方面&#xff0c;分别是Map端输入的小…

C/C++编程:令人印象深刻的高级技巧案例

C/C编程语言在软件开发领域有着悠久的历史&#xff0c;由于其高效、灵活和底层访问能力&#xff0c;至今仍然被广泛应用。本文将介绍一些在C/C编程中令人印象深刻的高级技巧&#xff0c;帮助读者提升编程水平&#xff0c;更加高效地使用这两种强大的编程语言。 一、指针运算与…