【数据结构篇】~栈和队列(附源码)

【数据结构篇】~栈和队列

前言

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作
的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 ​
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 ​
出栈:栈的删除操作叫做出栈。出数据也在栈顶。

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

一、栈的实现


1.头文件

c 复制代码
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//栈的实现很多和顺序表相同
typedef int stdatatype;
typedef struct stack
{
	stdatatype* arr;
	int capacity;//有效容量
	int top;//栈顶
}st;
void stinit(st* ps);// 初始化栈
void stdestroy(st* ps);// 销毁栈
void stpush(st* ps, stdatatype x);// 入栈
void stpop(st* ps);//出栈
stdatatype stTop(st* ps);//取栈顶元素
int stsize(st* ps);//获取栈中有效元素个数
bool stempty(st* ps);//栈是否为空

2.源文件

c 复制代码
#include"Stack.h"
void stinit(st* ps)// 初始化栈
{
	assert(ps);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;

}
bool stempty(st* ps)//栈是否为空(有效数据(top)为0)
{
	assert(ps);
	return ps->top==0;
}
void stdestroy(st* ps)// 销毁栈
{
	assert(ps);
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;//防止成为野指针
	ps->capacity = ps->top = 0;
}
void stpush(st* ps, stdatatype x)// 入栈(只能从栈顶入)
{
	assert(ps);
	if (ps->capacity == ps->top)//如果容量不够就要扩容
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		stdatatype* tmp = (stdatatype*)realloc(ps->arr,sizeof(stdatatype)*newcapacity );
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return 1;
		}
		ps->capacity = newcapacity;
		ps->arr = tmp;
	}
	//出if条件就说明容量足够
	ps->arr[ps->top++] = x;
}
void stpop(st* ps)//出栈
{
	assert(ps);
	assert(!stempty(ps));//如果报错就说明是空栈
	--ps->top;
}
stdatatype stTop(st* ps)//取栈顶元素
{
	assert(ps);
	assert(!stempty(ps));
	return ps->arr[ps->top - 1];
}
int stsize(st* ps)//获取栈中有效元素个数
{
	assert(ps);
	return ps->top;
}

3.一个算法题------有效的括号

c 复制代码
bool isValid(char* s) {
    st st;
    stinit(&st);
    if(*s=='\0')
    return false;
    else
    {
        while(*s != '\0')
        {
            //如果是左括号就入栈
            if(*s=='['
            ||*s=='{'
            ||*s=='(' )
            {
                stpush(&st, *s);
            }          
            else//左括号全部入栈,然后取栈顶元素和右括号匹配,然后出栈
            { if(stempty(&st))
              { 
                return false;
              }

              if(stTop(&st)=='('&& *s ==')'
              ||stTop(&st)=='{'&& *s =='}'
              ||stTop(&st)=='['&& *s ==']')
               {
                stpop(&st);//出栈
               }
               else{
                return false;
               }
            }
            s++;
        }
        bool ret=stempty(&st);
        stdestroy(&st);// 销毁栈
        return ret;
    }   
}

二、队列

概念:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先
出FIFO(First In First Out) ​
入队列:进行插入操作的一端称为队尾 ​
出队列:进行删除操作的一端称为队头

队列底层结构选型
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队
列在数组头上出数据,效率会比较低。

1.头文件

c 复制代码
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int qudatatype;
typedef struct queuenode {
	qudatatype data;
	struct queuenode* next;
}qunode;
typedef struct queue {
	qunode* phead;
	qunode* ptail;
	int size;//节点个数
}qu;
void quinit(qu* pq);//初始化队列
void qudestroy(qu* pq);//销毁队列
void qupush(qu* pq, qudatatype x);// 入队列,队尾
void qupop(qu* pq);// 出队列,队头
qudatatype qufront(qu* pq);//取队头数据
qudatatype quback(qu* pq);//取队尾数据
bool quempty(qu* pq);//队列判空
int qusize(qu* pq);//队列有效元素个数

2.源文件

c 复制代码
#include"Queue.h"
//队列底层是用单链表实现的
void quinit(qu* pq)//初始化队列
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
}
bool quempty(qu* pq)//队列判空
{
	assert(pq);
	return pq->phead == NULL;

}
void qupush(qu* pq, qudatatype x)// 入队列,队尾(单链表尾插)
{
	assert(pq);
	qunode* newnode = (qunode*)malloc(sizeof(qunode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return 1;
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	pq->ptail->next = newnode;
	pq->ptail = pq->ptail->next;
	pq->size++;
}
void qupop(qu* pq)// 出队列,队头(单链表头删)
{
	assert(pq);
	assert(!quempty(pq));
	if (pq->phead == pq->ptail)//只有一个节点是,要避免成为野指针
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;		
	}
	pq->phead = pq->phead->next;
}
void qudestroy(qu* pq)//销毁队列
{
	assert(pq);
	assert(!quempty(pq));
	while (pq->phead)
	{
		qunode* Next = pq->phead->next;
		free(pq->phead);
		pq->phead = NULL;
		pq->phead = Next;
	}//出循环时说明全部节点都释放了(除了phead、ptail)
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
int qusize(qu* pq)//队列有效元素个数
{
	assert(pq);
	return pq->size;
}
qudatatype qufront(qu* pq)//取队头数据(取数据时,队列不能为空!)
{
	assert(pq);
	assert(!quempty(pq));
	return pq->phead->data;

}
qudatatype quback(qu* pq)//取队尾数据
{
	assert(pq);
	assert(!quempty(pq));
	return pq->ptail->data;
}

详解都在注释中哦!

相关推荐
weixin_457885821 分钟前
JavaScript智能对话机器人——企业知识库自动化
开发语言·javascript·自动化
ChinaRainbowSea13 分钟前
1. 初始 RabbitMQ 消息队列
java·中间件·rabbitmq·java-rabbitmq
lmryBC4922 分钟前
golang接口-interface
java·前端·golang
ゞ 正在缓冲99%…23 分钟前
leetcode75.颜色分类
java·数据结构·算法·排序
孤独得猿24 分钟前
Qt常用控件第一部分
服务器·开发语言·qt
慕斯策划一场流浪29 分钟前
fastGPT—nextjs—mongoose—团队管理之团队列表api接口实现
开发语言·前端·javascript·fastgpt env文件配置·fastgpt团队列表接口实现·fastgpt团队切换api·fastgpt团队切换逻辑
橘猫云计算机设计35 分钟前
基于springboot的考研成绩查询系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·考研·django·毕业设计
时光呢40 分钟前
JAVA常见的 JVM 参数及其典型默认值
java·开发语言·jvm
橙橙子23041 分钟前
c++柔性数组、友元、类模版
开发语言·c++·柔性数组
程序媛学姐1 小时前
SpringKafka错误处理:重试机制与死信队列
java·开发语言·spring·kafka