首页 > 其他分享 >数据结构——队列和栈

数据结构——队列和栈

时间:2024-10-25 15:16:09浏览次数:9  
标签:struct 队列 复杂度 list int 数据结构 stack

目录

一、栈

        1、概念与结构

        2、栈的结构与初始化

        3、入栈

        4、出栈 

        5、取栈顶元素 

        6、取栈中有效元素个数 

         7、栈是否为空

 二、队列

         1、概念与结构

        2、队列的结构与初始化

         3、入队列

         4、出队列

         5、取队头数据

         6、取队尾数据

         7、队列判空

         8、队列中有效元素个数

 练习题目链


一、栈

        1、概念与结构

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

        压栈:栈的插⼊操作叫做进栈/压栈/⼊栈,⼊数据在栈顶。

        出栈:栈的删除操作叫做出栈。出数据也在栈顶。

        栈的底层逻辑实现,可以是使用顺序表实现也可以使用链表表实现,我这里采用的是动态顺序表实现

        栈的实现⼀般可以使⽤数组或者链表实现,相对⽽⾔数组的结构实现更优⼀些。因为数组在尾上插⼊数据的代价⽐较⼩

        2、栈的结构与初始化

// 栈——后进先出
struct stack
{
	int* data;//栈
	int top;//栈顶元素位置
	int capacity;//栈的容量
};

//栈初始化
void stackinit(struct stack* stack)
{
	//设置栈顶位置
	stack->top = 0;
	//初始栈的容量为4
	stack->capacity = 4;
	//创建数组
	stack->data = (int*)malloc(sizeof(int) * stack->capacity);
}

        3、入栈

         时间复杂度:O( 1 )

        在栈的结构中 top 时刻记录着栈顶的位置,直接插入即可,因此时间复杂度为O( 1 )

        注意在插入前要检查栈是否已经满了,如果满了要扩容 

//栈顶插入元素
void stackpush(struct stack* stack, int x)
{
	//判断是否需要扩容
	if (stack->top == stack->capacity)
	{
		//扩容至当前栈容量的两倍
		stack->capacity = stack->capacity * 2;
		//更新栈
		int* newstack = (int*)realloc(stack->data, sizeof(int) * stack->capacity);
		//创建失败
		if (newstack)
		{
			assert("error");
		}
		stack->data = newstack;
	}
	//栈顶插入元素
	stack->data[stack->top] = x;
	//栈顶加一
	stack->top++;
}

        4、出栈 

         时间复杂度:O( 1 )

         在栈的结构中 top 时刻记录着栈顶的位置,直接减少栈中有效元素即可,因此时间复杂度为O( 1 )

//栈顶删除元素
void stackpop(struct stack* arr)
{
	//栈不能为空
	if (arr->top == 0)
	{
		return;
	}
	//出栈
	arr->top--;
}

        5、取栈顶元素 

        时间复杂度:O( 1 )

         在栈的结构中 top 时刻记录着栈顶的位置,直接返回即可,因此时间复杂度为O( 1 )

//查找栈顶元素
int stacktop(struct stack* arr)
{
	//栈不能为空
	if (arr->top != 0)
	{
		assert("stack is NULL");
	}
	//返回栈顶元素
	return arr->data[(arr->top) - 1];
}

        6、取栈中有效元素个数 

        时间复杂度:O( 1 )

         在栈的结构中 top 时刻记录着栈顶的位置,也是栈中有效元素个数直接返回即可,因此时间复杂度为O( 1 )

//查找栈中元素个数
int stacksize(struct stack* arr)
{
	//查找栈中元素个数
	return arr->top;
}

         7、栈是否为空

         时间复杂度:O( 1 )

        判断栈中元素个数是否为零 

//判断栈是否为空
int stackempty(struct stack* arr)
{
	//判断栈是否为空
	if (arr->top != 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

 二、队列

         1、概念与结构

        队列:只允许在⼀端进⾏插⼊数据操作,在另⼀端进⾏删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)

        ⼊队列:进⾏插⼊操作的⼀端称为队尾

        出队列:进⾏删除操作的⼀端称为队头

         队列也可以数组和链表的结构实现,使⽤链表的结构实现更优⼀些,因为如果使⽤数组的结构,出队列在数组头上出数据,效率会⽐较低,这里我使用链表实现

        2、队列的结构与初始化

//队列节点
struct queuenode
{
	int data;//存储数据
	struct queuenode* next;//下一个元素的地址
};
//队列,维护队列的队尾和对头
struct queue
{
	struct queuenode* head;//队头
	struct queuenode* tail;//队尾
	int size;//队列有效元素个数
};
//队列初始化
void queueinit(struct queue* queue)
{
	//初始为空
	queue->head = NULL;
	queue->tail = NULL;
	//初始队列中元素个数为0
	queue->size = 0;
}

         3、入队列

        时间复杂度:O( 1 ) 

        我们有维护队列的尾节点,创建一个新节点在尾节点后插入同时更新尾节点的指向 ,因此时间复杂度为O( 1 )

//队列——插入
void queuepush(struct queue* list, int x)
{
	//创建队列节点,并初始化
	struct queuenode* node = calloc(1, sizeof(struct queuenode));
	node->data = x;
	node->next = NULL;
	//队列中没有元素时,对头和队尾都为新创建的节点
	if (list->head == NULL)
	{
		list->head = node;
		list->tail = node;
	}
	else
	{
		//队尾的下一个节点为新创建的节点
		list->tail->next = node;
		//更改队尾节点的指向
		list->tail = node;
	}
	//队列有效元素个数加一
	list->size++;
}

         4、出队列

         时间复杂度:O( 1 ) 

        删除头节点,并更新头节点为头节点的下一个节点, 因此时间复杂度为O( 1 )

//队列——删除
void queuepop(struct queue* list)
{
	//队列不能为空
	if (list->head == NULL)
	{
		assert(list->head);
	}
	//保存对头的下一个节点
	struct queuenode* cur = list->head->next;
	//删除队头
	free(list->head);
	//更改对头的指向
	list->head = cur;
	//当对头为空时,队尾也要为空
	if (cur == NULL)
	{
		list->tail = NULL;
	}
	//队列有效元素减一
	list->size--;
}

         5、取队头数据

         时间复杂度:O( 1 ) 

        这里有维护头节点,直接返回头节点数据,因此时间复杂度为O( 1 )

//队列——返回对头数据
int queuefront(struct queue* list)
{
	//队列不能为空
	if (list->head == NULL)
	{
		assert(list->head);
	}
	//返回对头数据
	return list->head->data;
}

         6、取队尾数据

        时间复杂度:O( 1 )  

        这里有维护尾节点,直接返回头节点数据,因此时间复杂度为O( 1 ) 

//队列——返回队尾数据
int queueback(struct queue* list)
{
	//队列不能为空
	if (list->tail == NULL)
	{
		assert(list->tail);
	}
	//返回队尾数据
	return list->tail->data;
}

         7、队列判空

         时间复杂度:O( 1 )  

        判断队列中的有效元素个数是否为0 

//队列——判断队列是否为空
int queueempty(struct queue* list)
{
	//队列——判断队列是否为空
	if (list->head == NULL)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

         8、队列中有效元素个数

        时间复杂度:O( 1 )  

         这里有维护队列中有效元素个数,直接返回,因此时间复杂度为O( 1 )

//队列——返回队列有效元素个数
int queuesize(struct queue* list)
{
	//返回答案
	return list->size;
}

 练习题目链

        数据结构最好的巩固就是写算法题目也是最好的体现,学习了不代表学会了,一定要加以实践

        20. 有效的括号 - 力扣(LeetCode) 

        225. 用队列实现栈 - 力扣(LeetCode) 

        232. 用栈实现队列 - 力扣(LeetCode)

        155. 最小栈 - 力扣(LeetCode) 

        更多的可以在力扣上写: 力扣 (LeetCode) 全球极客挚爱的技术成长平台

标签:struct,队列,复杂度,list,int,数据结构,stack
From: https://blog.csdn.net/LVZHUO_2022/article/details/143218783

相关文章

  • 数据结构 ——— C语言实现链式队列
    目录队列的概念以及示意图数组队列和链式队列链式队列的结构 实现链式队列的准备工作实现链式队列1.初始化2.打印队列的所有数据3.数据入队列(尾插)4.数据出队列(头删)5.访问队头的数据6.访问队尾的数据7.队列数据总个数8.判断队列是否为空9.释放队列的所......
  • 数据结构 ——— C语言实现数组栈
    目录栈的概念以及示意图链式栈和数组栈链式栈:数组栈:数组栈的结构实现数组栈的准备工作实现数组栈初始化数组栈入栈(尾插)出栈(尾删)访问栈顶数据判断栈是否为空栈数据的总数访问栈的所有数据释放栈Stack.h的所有代码Stack.c的所有代码栈的概念以及示意图栈......
  • 数据结构有哪些
    数据结构分类涉及多方面,主要包括:1、线性结构、2、树形结构、3、图形结构、4、集合结构、5、文件结构。在这些种类中,线性结构是最基本、也是最为广泛使用的一种,它包括数组、链表、栈和队列等数据结构,通过线性的方式组织数据元素。以数组为例,它以连续的内存空间顺序存储数据,通过索引......
  • 基础数据结构(1)
    单链表与双链表的用处单链表单链表的存储:单链表的几种操作在表头插入一个数:先将这个数指向head指向的数,再将head指向这个数在表中的第k位后面插入一个数:先将这个数指向第k位指向的数,再将第k位指向这个数在表中删除一个数:让这个数直接指向下一个数的下一个数代码实现:/......
  • 数据结构 - 树,三探之代码实现
    数据结构-树,三探之代码实现 本文介绍了使用数组和链表两种方式实现二叉树,包括初始化、节点操作(如获取、添加、删除)、以及遍历方法(前序、中序、后序、层次遍历)。测试代码已上传至代码库。 书接上回,今天和大家一起动手来自己实现树。相信通过前面的章节学习,大家已经明白树......
  • 数据结构 - 堆
    今天我们将学习新的数据结构-堆。01、定义堆是一种特殊的二叉树,并且满足以下两个特性:(1)堆是一棵完全二叉树;(2)堆中任意一个节点元素值都小于等于(或大于等于)左右子树中所有节点元素值;小根堆,根节点元素永远是最小值,即堆中每个节点元素值都小于等于左右子树中所有节点元素值;大根......
  • 数据结构补充
    P1972[SDOI2009]HH的项链求[l,r]区间中颜色的数量#include<cstdio>#include<algorithm>#include<vector>#definefo(i,a,b)for(int(i)=(a);(i)<=(b);(i)++)usingnamespacestd;constintN=1e6+5;intc[N],ans,s;intn,m,x,op,p[N],t[N],a[N],f[N],g[......
  • C++ 双端队列实现
    #include<iostream>usingnamespacestd;#defineullisize_ttemplate<classT>classDualStack{private: structNode{ Tdata; Node*next; }; Node*head,*tail; Node*p; ullilength;public: DualStack(){ head=NULL; length=0......
  • 新高一暑假第一期集训恢复性训练【数据结构-线段树晚测】(补)
    新高一暑假第一期集训恢复性训练【数据结构-线段树晚测】(补)A.[CF1045G]AIrobots我们先按视野降序排序,这样一个一个考虑,如果后面的能看到前面,那前面的也肯定能看到后面。这样,就是对于每一个机器人,在他前面有几个智商在\([q-k,q+k]\),位置在\([x-r,x+r]\)。那么把这个东......
  • 延时队列(RabbitMQ)
    1.概述延时任务,也叫延迟任务延迟队列:没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发另一个事件,任务可以立即执行,也可以延迟。2.技术选型RabbitMQ(死信交换机)实现方式TTL+私信交换机1.概述死信队列:存放死信的队列死信交换机:绑定死信队列......