数据结构:栈和队列

这篇具有很好参考价值的文章主要介绍了数据结构:栈和队列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

朋友们、伙计们,我们又见面了,本期来给大家解读一下栈和队列方面的相关知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个 人 主 页 :  stackY、

目录

前言: 

1.栈

1.1栈的概念及结构

1.2栈的实现

1.2.1栈的创建

1.2.2栈的初始化

1.2.3入栈

1.2.4检测栈是否为空

1.2.5出栈 

1.2.6获取栈顶元素

1.2.7获取栈中有效元素的个数

1.2.8销毁栈

1.2.9访问栈

1.3栈的完整代码

2.队列 

2.1队列的概念及结构

2.2队列的实现

2.2.1队列的创建

2.2.2队列的初始化

2.2.3队尾入队列

2.2.4检测队列是否为空

2.2.5队头出队列

2.2.6获取队头数据

2.2.7获取队尾数据

2.2.8获取队列有效元素个数

2.2.9销毁队列

2.2.10访问队列

2.3队列完整代码


前言: 

在之前的顺序表中我们提到过线性表:线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。
顺序表的实现我们使用的是数组,链表的实现我们使用的是链式结构,那么关于栈和队列又该怎么样实现呢?话不多说,直接开始:

1.栈

1.1栈的概念及结构

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

1.2栈的实现

我们以STL为模板来实现栈,因此栈的功能也就分为:初始化、销毁、入栈、出栈、获取栈顶元素、获取栈中有效元素个数、检测栈是否为空。

栈的实现还是和之前的数据结构的实现一样分模块来写, 当然也是可以在一个源文件中完成的,当然小编还是推荐大家分模块来写,先创建两个源文件:Test.c和Stack.c,再创建一个头文件:Stack.h,这里的文件命名不做要求,表示的有意义就行。同样的我们在Test.c中实现基本逻辑,在Stack.c中实现栈的细节,在Stack.h中进行函数声明和头文件包含等,话不多说,我们直接开始:

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为我们的入栈和出栈都是在尾部进行操作,如果使用链表的话,在进行入栈的时候还得找尾,在出栈的时候还得找尾的前一个,代价有点大,所以选择数组,因为数组在尾上插入数据的代价比较小。

1.2.1栈的创建

栈的创建有两种方式:

1.静态栈

头文件:Stack.h

//静态栈
typedef int STDataType;
#define N 10
typedef struct Stack
{
	STDataType _a[N];
	int _top; // 栈顶
}Stack;

2.动态栈

头文件:Stack.h

//动态栈
typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;        //栈顶
	int capacity;  //栈的容量
}Stack;

由于静态栈不常用也不实用,所以在这里我们就来使用动态栈:

1.2.2栈的初始化

在创建栈的时候栈中有一个指针,栈顶,和栈的容量,因此我们要将这些数据初始化一下,先将指针置为NULL,再将容量置为0,这里的栈顶初始化就有两种说法了:

1.如果将top置为0的话,那么在插入数据的时候是先插入然后top++,在插入完之后top始终指向的是最后一个数据的下一个位置。

2.如果将top置为-1,那么就要先top++然后再插入数据,再插入完之后top指向的是最后一个数据的位置。

两种方式都可行,但是将top置为0在后面的操作中会比较方便。

头文件:Stack.h

//对栈的初始化
void StackInit(Stack* pst);

源文件:Stack.c

//对栈的初始化
void StackInit(Stack* pst)
{
	assert(pst);
	pst->a = NULL;
	//top为-1时,插入一个数据之后top指向的是刚刚插入数据的位置
	//pst->top = -1     
	//top为0时,插入一个数据之后top指向的是刚刚插入数据后面的位置
	pst->top = 0;
	pst->capacity = 0;
}

注意:这里传参为什么不用二级指针,因为我们改变的是结构体成员,使用结构体指针就完全OK。

1.2.3入栈

入栈也叫做插入数据,先要检测容量,如果top等于容量,那么就需要扩容,然后将数据插入到top的位置,然后top++:

数据结构:栈和队列

头文件:Stack.h

//入栈
void StackPush(Stack* pst, STDataType x);

源文件:Stack.c

//入栈
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	//检测容量
	if (pst->top == pst->capacity)
	{
		int NewCapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		//当pst->a为NULL时执行的功能是和malloc一样
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * NewCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = NewCapacity;
	}
	//入栈
	pst->a[pst->top] = x;
	pst->top++;
}

1.2.4检测栈是否为空

检测栈是否为空:就是检测栈顶是否为0,如果栈顶top为0,则为空,栈为空返回true,不为空返回false:

头文件:Stack.h

//检测栈是否为空
bool StackEmpty(Stack* pst);

源文件:Stack.c

//检测栈是否为空
bool StackEmpty(Stack* pst)
{
	assert(pst);
	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return pst->top == 0;
}

1.2.5出栈 

出栈就比较简单了,直接将top--,但是这里还存在一个问题,如果栈为空,那么就不能再出栈,因此我们需要对栈进行判空:

数据结构:栈和队列

头文件:Stack.h

//出栈
void StackPop(Stack* pst);

源文件:Stack.c

//出栈
void StackPop(Stack* pst)
{
	assert(pst);
	//判断栈是否为空
	assert(!StackEmpty(pst));
	//出栈
	pst->top--;
}

1.2.6获取栈顶元素

获取栈顶元素就是将数组中下标为top-1的元素返回,并且在返回前先要判断栈中是否有无数据:

头文件:Stack.h

//获取栈顶元素
STDataType StackTop(Stack* pst);

源文件:Stack.c

//获取栈顶元素
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	//top指向的是栈顶的下一个位置的元素
	return pst->a[pst->top-1];
}

1.2.7获取栈中有效元素的个数

栈中有效元素的个数就是top,只需要将top直接返回即可:

头文件:Stack.h

//获取栈中的有效元素的个数
int StackSize(Stack* pst);

源文件:Stack.c

//获取栈中的有效元素的个数
int StackSize(Stack* pst)
{
	assert(pst);

	return pst->top;
}

1.2.8销毁栈

由于我们创建的是动态的栈,因此在程序结束之后我们需要将动态开辟的空间释放掉,然后将top和capacity都置为0:
头文件:Stack.h

//销毁栈
void StackDestroy(Stack* pst);

源文件:Stack.c

//销毁栈
void StackDestroy(Stack* pst)
{
	assert(pst);

	//释放
	free(pst->a);
	pst->a = NULL;
	//重置为0
	pst->top = pst->capacity = 0;
}

1.2.9访问栈

上面的这些接口都比较简单,那么在实现上面的接口之后怎么访问栈呢?我们可以通过循环来进行访问,循环的判断条件就是栈不为空,然后打印栈顶的元素,然后再删除栈顶的元素,依次类推,就可以访问栈中的全部元素了:

源文件:Test.c

#include "Stack.h"

void TestStack()
{
	Stack st;
	//初始化
	StackInit(&st);

	//入栈
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);

	//获取栈中的有效元素的个数
	printf("Size:%d\n", StackSize(&st));

	//访问栈的元素
	while (!StackEmpty(&st))
	{
		//打印栈顶的数据
		printf("%d ", StackTop(&st));
		//出栈
		StackPop(&st);
	}

	//销毁栈
	StackDestroy(&st);
}

int main()
{
	TestStack();
	return 0;
}

数据结构:栈和队列

1.3栈的完整代码

头文件:Stack.h

#pragma once

//   栈的实现

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

//动态栈
typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;        //栈顶
	int capacity;  //栈的容量
}Stack;


//对栈的初始化
void StackInit(Stack* pst);

//入栈
void StackPush(Stack* pst, STDataType x);

//出栈
void StackPop(Stack* pst);

//获取栈顶元素
STDataType StackTop(Stack* pst);

//获取栈中的有效元素的个数
int StackSize(Stack* pst);

//检测栈是否为空
bool StackEmpty(Stack* pst);

//销毁栈
void StackDestroy(Stack* pst);

源文件:Stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

//对栈的初始化
void StackInit(Stack* pst)
{
	assert(pst);
	pst->a = NULL;
	//top为-1时,插入一个数据之后top指向的是刚刚插入数据的位置
	//pst->top = -1     
	//top为0时,插入一个数据之后top指向的是刚刚插入数据后面的位置
	pst->top = 0;
	pst->capacity = 0;
}

//入栈
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	//检测容量
	if (pst->top == pst->capacity)
	{
		int NewCapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		//当pst->a为NULL时执行的功能是和malloc一样
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * NewCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = NewCapacity;
	}
	//入栈
	pst->a[pst->top] = x;
	pst->top++;
}

//出栈
void StackPop(Stack* pst)
{
	assert(pst);
	//判断栈是否为空
	assert(!StackEmpty(pst));
	//出栈
	pst->top--;
}

//获取栈顶元素
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	//top指向的是栈顶的下一个位置的元素
	return pst->a[pst->top-1];
}

//获取栈中的有效元素的个数
int StackSize(Stack* pst)
{
	assert(pst);

	return pst->top;
}

//检测栈是否为空
bool StackEmpty(Stack* pst)
{
	assert(pst);
	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return pst->top == 0;
}

//销毁栈
void StackDestroy(Stack* pst)
{
	assert(pst);

	//释放
	free(pst->a);
	pst->a = NULL;
	//重置为0
	pst->top = pst->capacity = 0;
}

源文件:Test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

void TestStack()
{
	Stack st;
	//初始化
	StackInit(&st);

	//入栈
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);

	//获取栈中的有效元素的个数
	printf("Size:%d\n", StackSize(&st));

	//访问栈的元素
	while (!StackEmpty(&st))
	{
		//打印栈顶的数据
		printf("%d ", StackTop(&st));
		//出栈
		StackPop(&st);
	}

	//销毁栈
	StackDestroy(&st);
}


int main()
{
	TestStack();
	return 0;
}

2.队列 

2.1队列的概念及结构

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

2.2队列的实现

我们以STL为模板来实现队列,因此队列的功能也就分为:初始化、销毁、入列、出列、获取队头元素、获取队尾元素,获取队列中有效元素个数、检测队列是否为空。

队列的实现还是和之前的数据结构的实现一样分模块来写, 当然也是可以在一个源文件中完成的,当然小编还是推荐大家分模块来写,先创建两个源文件:Test.c和Queue.c,再创建一个头文件:Queue.h,这里的文件命名不做要求,表示的有意义就行。同样的我们在Test.c中实现基本逻辑,在Queue.c中实现队列的细节,在Queue.h中进行函数声明和头文件包含等,话不多说,我们直接开始:

队列也可以使用数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,每一次出一个数据都要将后面的数据挪动,代价大,效率低,使用链表可以直接今天头删,和尾插。
数据结构:栈和队列

2.2.1队列的创建

队列的实现使用链表比较合适,因此我们需要先创建一个单链表表示链式结构,由于单链表尾插每次都需要找尾,效率比较低,所以我们可以再创建一个队列结构,这个队列结构中包含这个队列的头、尾、有效元素个数:

头文件:Queue.h

//链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

//队列的结构
typedef struct Queue
{
	//头指针
	QNode* phead;
	//尾指针
	QNode* ptail;
	//队列中有效元素个数
	int size;
}Queue;

2.2.2队列的初始化

初始化队列比较简单,将队列中的头、尾指针置为NULL,再将有效元素个数置为0:

头文件:Queue.h

//初始化队列
void QueueInit(Queue* pq);

源文件:Queue.c

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);

	pq->phead = NULL;
	pq->ptail= NULL;
	pq->size = 0;
}

2.2.3队尾入队列

从队尾插入队列就相当于尾插,先创建一个新结点,表示要插入的结点,这时就要区分第一次插入和后面几次插入,第一次插入时要注意空指针的问题,队列为空的条件是头指针和尾指针都为空,后面的插入直接链接到尾,然后更新尾,然后将有效元素个数加一:

数据结构:栈和队列

数据结构:栈和队列  

头文件:Queue.h

//队尾入队列
void QueuePush(Queue* pq, QDataType x);

源文件:Queue.c

//队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	
	//创建新的结点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->next = NULL;
	newnode->data = x;

	//第一次尾插
	if (pq->ptail == NULL)
	{
		assert(pq->phead == NULL);

		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	//有效元素++
	pq->size++;
}

2.2.4检测队列是否为空

在出队列时先要进行对队列的检查,检测队列是否为空,若为空就不能再进行删除,实现这个接口有两种方式:

1.头指针和尾指针都指向空。

2.队列中有效元素个数为空。

根据个人习惯来进行使用

头文件:Queue.h

//检测队列是否为空
bool QueueEmpty(Queue* pq);

源文件:Queue.c

//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	//1.判断头、尾指针
	/*
	return pq->phead == NULL
		&& pq->ptail == NULL;
	*/

	//2.判断有效元素个数
	return pq->size == 0;
}

2.2.5队头出队列

队头出队列就表示头删,因此先要判断队列中是否有数据,然后进行头删,头删的话需要保存头的后一个结点,然后将头结点释放,再将新的头指向保存的结点,然后再将有效元素个数减一,这样子就完成了头删,但是如果我们仔细画图的话就会发现,这样删除的话并不完美,当只有一个结点的时候,进行头删的话这里的尾指针就变成了野指针,所以还是得区分两种情况,只有一个结点和有多个结点,如果只有一个结点,那么直接进行释放,然后将头尾结点都置为NULL,有多个结点的话可以直接释放:

数据结构:栈和队列

数据结构:栈和队列

数据结构:栈和队列

头文件:Queue.h

//对头出队列
void QueuePop(Queue* pq);

源文件:Queue.c

//队头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	//判空
	assert(!QueueEmpty(pq));

	//一个结点
	if (pq->phead->next == NULL)
	{
		//直接释放
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	//多个结点
	else
	{
		//记录头的下一个
		QNode* Next = pq->phead->next;
		//释放
		free(pq->phead);
		//更新头结点
		pq->phead = Next;
	}
	
	pq->size--;
}

2.2.6获取队头数据

队头数据就是头指针的结点中的data,如果队列是空队列则不能获取,所以先得判断一下:

头文件:Queue.h

//获取队头的元素
QDataType QueueFront(Queue* pq);

源文件:Queue.c

//获取队头的元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	//先判空
	assert(!QueueEmpty(pq));

	return pq->phead->data;
}

2.2.7获取队尾数据

队尾数据就是尾指针的结点中的data,如果队列是空队列则不能获取,所以先得判断一下:

头文件:Queue.h

//获取队尾的元素
QDataType QueueBack(Queue* pq);

源文件:Queue.c

//获取队尾的元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	//先判空
	assert(!QueueEmpty(pq));

	return pq->ptail->data;
}

2.2.8获取队列有效元素个数

有效元素个数就是size,可直接进行返回:

头文件:Queue.h


//获取队列有效元素的个数
int QueueSize(Queue* pq);

源文件:Queue.c

//获取队列有效元素的个数
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

2.2.9销毁队列

由于链式结构的每一个结点都是动态开辟的,因此在程序结束之后我们需要将这些结点一一释放掉,这里要注意,即便是空队列也要进行释放,空队列只表示结点中没有数据,但不能表示没有结点,所以空队列也是要进行释放,销毁队列也有两种方式,大家根据习惯来进行使用:

1.保存当前结点,然后释放。

2.保存下一个结点,然后释放当前结点。

头文件:Queue.h

//销毁队列
void QueueDestroy(Queue* pq);

源文件:Queue.c

//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

2.2.10访问队列

当我们完成上述接口时,可以来测试一下,顺便对队列进行访问,访问的时候依旧是队列不为空我们就可以访问,每一次访问的是队头的元素,然后将队头的元素出列,再访问下一个元素,依次类推:

源文件:Test.c

void TestQueue()
{
	Queue q;
	
	//初始化
	QueueInit(&q);

	//入列
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);

	//有效元素个数
	printf("Size:%d\n", QueueSize(&q));

	//访问队头元素
	printf("Front:%d\n", QueueFront(&q));

	//访问队尾元素
	printf("Back:%d\n", QueueBack(&q));

	//访问队列
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}

	//销毁
	QueueDestroy(&q);
}


int main()
{
	TestQueue();
	return 0;
}

数据结构:栈和队列

2.3队列完整代码

头文件:Queue.h

#pragma once

//       队列

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

//链式结构:表示队列
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

//队列的结构
typedef struct Queue
{
	//头指针
	QNode* phead;
	//尾指针
	QNode* ptail;
	//队列中有效元素个数
	int size;
}Queue;


//初始化队列
void QueueInit(Queue* pq);

//销毁队列
void QueueDestroy(Queue* pq);

//队尾入队列
void QueuePush(Queue* pq, QDataType x);

//检测队列是否为空
bool QueueEmpty(Queue* pq);

//对头出队列
void QueuePop(Queue* pq);

//获取队头的元素
QDataType QueueFront(Queue* pq);

//获取队尾的元素
QDataType QueueBack(Queue* pq);

//获取队列有效元素的个数
int QueueSize(Queue* pq);

 源文件:Queue.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Queue.h"

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);

	pq->phead = NULL;
	pq->ptail= NULL;
	pq->size = 0;
}

//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

//队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	
	//创建新的结点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->next = NULL;
	newnode->data = x;

	//第一次尾插
	if (pq->ptail == NULL)
	{
		assert(pq->phead == NULL);

		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	//有效元素++
	pq->size++;
}

//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	//1.判断头、尾指针
	/*
	return pq->phead == NULL
		&& pq->ptail == NULL;
	*/

	//2.判断有效元素个数
	return pq->size == 0;
}

//队头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	//判空
	assert(!QueueEmpty(pq));

	//一个结点
	if (pq->phead->next == NULL)
	{
		//直接释放
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	//多个结点
	else
	{
		//记录头的下一个
		QNode* Next = pq->phead->next;
		//释放
		free(pq->phead);
		//更新头结点
		pq->phead = Next;
	}
	
	pq->size--;
}

//获取队头的元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	//先判空
	assert(!QueueEmpty(pq));

	return pq->phead->data;
}

//获取队尾的元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	//先判空
	assert(!QueueEmpty(pq));

	return pq->ptail->data;
}

//获取队列有效元素的个数
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}


源文件:Test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Queue.h"

void TestQueue()
{
	Queue q;
	
	//初始化
	QueueInit(&q);

	//入列
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);

	//有效元素个数
	printf("Size:%d\n", QueueSize(&q));

	//访问队头元素
	printf("Front:%d\n", QueueFront(&q));

	//访问队尾元素
	printf("Back:%d\n", QueueBack(&q));

	//访问队列
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}

	//销毁
	QueueDestroy(&q);
}


int main()
{
	TestQueue();
	return 0;
}

今天的博客就分享到这里,喜欢的老铁留下你的三连,感谢感谢!我们下期再见!! 文章来源地址https://www.toymoban.com/news/detail-457791.html

到了这里,关于数据结构:栈和队列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构---栈和队列

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

    2024年01月18日
    浏览(41)
  • 数据结构--栈和队列

    栈是一种常见的数据结构,它遵循 后进先出LIFO (Last In First Out)的原则。 进行数据插入和操作的一端称为栈顶,另一端称为栈底 。 压栈 :栈的插入操作被称为压栈/进栈/入栈,入数据在栈顶。 出栈 :栈的删除操作。出数据也在栈顶; 栈可以用 数组 或者是 链表 来实现;

    2024年02月09日
    浏览(41)
  • 数据结构——栈和队列

    目录  一.前言 二.前文回顾 三.栈 3.1 栈的概念及结构 3.2 栈的实现 3.2.1 初始化函数 3.2.2 销毁函数 3.2.3 入栈函数 3.2.4 出栈函数 3.2.5 计算大小函数 3.2.6 空栈函数 3.2.7 获取栈顶函数  3.2.8 小测试 3.3 全部代码 四.栈的练习 4.1 有效的括号 五.队列 5.1队列的概念及结构 5.2 队列的实

    2024年01月25日
    浏览(47)
  • 数据结构【栈和队列】

    一、栈 1.定义:只允许一端进行插入和删除的线性表,结构与手枪的弹夹差不多,可以作为实现递归函数(调用和返回都是后进先出)调用的一种数据结构; 栈顶:允许插入删除的那端; 栈底:固定的,不允许插入或删除; 空栈:不含元素; 2.特点:后进先出; 3.操作:入

    2024年02月15日
    浏览(50)
  • 【数据结构】栈和队列(链表模拟队列)

      学习本章节必须具备 单链表的前置知识, 建议提前学习:点击链接学习:单链表各种功能函数 细节 详解 本章节是学习用 单链表模拟队列 1. 单链表实现队列 思路如下 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先 进先出

    2024年04月27日
    浏览(44)
  • 数据结构3:栈和队列

    目录 1.栈 1.1栈的概念及结构 ​1.2栈的实现 2.队列 2.1队列的概念及结构  2.2队列的实现 2.3循环队列 ​3.栈和队列的面试题 4.概念选择题 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除的一端称为栈顶,另一端称为栈底。 栈中数

    2023年04月27日
    浏览(42)
  • 【数据结构】2.栈和队列

    【数据结构】1.线性表的数组描述和链式描述 - imXuan - 博客园 (cnblogs.com) 【数据结构】1.线性表的数组描述和链式描述 - imXuan - 博客园 (cnblogs.com) 队列由一个数组来描述,队首指针是队首的前一个元素,队尾指针是队尾所在元素,当队首和队尾指针重叠时表示队列为空;当 (队

    2024年02月08日
    浏览(41)
  • 【数据结构】栈和队列(栈篇)

    目录 1.栈的概念及结构 2.栈的实现 2.1栈的结构体定义 2.2栈的常用接口函数 🐾栈的初始化 🐾插入数据 🐾删除数据 🐾取栈顶元素 🐾判断栈是否为空 🐾计算栈的大小 🐾栈的销毁 2.3完整的代码  3.与栈有关的面试题 栈: 一种特殊的线性表,其只允许在固定的一端进行插入

    2024年02月12日
    浏览(38)
  • 数据结构栈和队列

    3.1栈和队列的定义和特点 栈和队列是两种常用的、重要的数据结构 栈和队列是限定插入和删除只能在表的 “ 端点 ”进行的 线性表 栈和队列是线性表的子集(是插入和删除位置受限的线性表) 栈的应用: ​ 由于栈的操作具有 后进先出 的固有特性,使得栈成为程序设计中

    2024年02月16日
    浏览(34)
  • 考研数据结构--栈和队列

    内容 栈 :栈的抽象数据类型定义、栈的存储表示及基本操作实现、栈的应用 栈的定义(特点) 栈是一种后进先出(LIFO)的线性表,只能在一端进行插入和删除操作,这一端称为栈顶,另一端称为栈底。 打个比方: 有一个胡同很窄只能通过一辆车,而且是死胡同,只能从胡

    2023年04月19日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包