栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C/C++【数据结构笔记】(栈和队列)(超详细总结和细节)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C/C++【数据结构笔记】(栈和队列)(超详细总结和细节)

文章目录
  • 栈和队列
    • 1.栈stack
      • 1.1栈的概念及结构
      • 1.2栈实现
      • 1.3栈头文件
      • 1.4栈源文件
      • 1.5主函数实现
    • 2.队列
    • 2.1队列的概念及结构
    • 2.2队列的实现
      • 2.3队列头文件
      • 2.4队列源文件
      • 2.5主函数实现
      • 2.6环形队列
    • 栈和队列区别与联系

栈和队列 1.栈stack 1.1栈的概念及结构

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

LIFO是栈的特点,栈接口函数数据插入和删除操作都是在栈顶实现:

1.2栈实现

栈先进后出的特点决定其可以使用数组或者链表来实现,相对而言,数组结构会更优一些,单向链表实现栈时,入栈和出栈都需要遍历(O(N)的时间复杂度);即使是带有尾指针的单向链表,出栈任然需要遍历(O(N));双向链表很完美,但占用空间显然大于数组。综上所述,数组性能更优。如下:

栈实现简述:实际上就是用顺序表,通过改变函数接口,达到后进先出的效果。静态顺序表就是实现静态栈,动态顺序表实现的则是动态栈。我们一般用动态栈。

1.3栈头文件
#pragma once
#include
#include
using namespace std;
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;  
	int top;        //栈顶
	int capacity;   //容量
}Stack;
//初始化栈
void StackInit(Stack* ps);
//销毁栈
void StackDestory(Stack* ps);
//入栈
void StackPush(Stack* ps, STDataType x);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
STDataType StackTop(Stack* ps);
//获取栈中有效的元素个数
int StackSize(Stack* ps);
//判断栈是否为空,空则返回非零,不为空则返回0
bool StackEmpty(Stack* ps); 
1.4栈源文件
#include"Stack.h"
void StackInit(Stack* ps)//初始化
{
	assert(ps);//断言判断是否为空
	//凡是传进来指针,就断言判断。凡是申请指针空间,就要判断是否成功!
	ps->a = (STDataType*)malloc(4 * sizeof(STDataType));
	if (ps->a == NULL)
	{
		cout << "malloc failed" << endl;
		exit(-1);
	}
	ps->capacity = 4;
	ps->top = 0; 
}

void StackDestory(Stack* ps)//销毁栈
{
	assert(ps);//断言判断是否为空
	free(ps->a);
	ps->a = NULL;//释放完指针要置空,否则就是野指针
	ps->top = ps->capacity=0;
}

void StackPush(Stack* ps, STDataType x)//入栈
{
	assert(ps);//断言判断是否为空
	if (ps->top == ps->capacity)
	{
		STDataType* tmp =(STDataType*)realloc(ps->a,2 * ps->capacity * sizeof(STDataType));
		//凡是传进来指针,就断言判断。凡是申请指针空间,就要判断是否成功!
		if (tmp == NULL)
		{
			cout << "realloc failed" << endl;
			exit(-1);//exit(0)表示正常退出,exit(x)x非零表示非正常退出
		}
		else
		{
			ps->a = tmp;
			ps->capacity *= 2;
		}
	}
	ps->a[ps->top] = x;
	ps->top++;
}

void StackPop(Stack* ps)//出栈
{
	assert(ps);//断言判断是否为空
	assert(ps->top);//栈空
	//ps->a[ps->top]=0;是不可取的!
	ps->top--;
}

STDataType StackTop(Stack* ps)//获取栈顶元素
{
	assert(ps);//断言判断是否为空
	assert(ps->top > 0);//栈空
	return ps->a[ps->top - 1];
}

//获取栈中有效的元素个数
int StackSize(Stack* ps)
{
	assert(ps);//断言判断是否为空
	return ps->top;
}

bool StackEmpty(Stack* ps) //判断栈是否为空,空则返回1,不为空则返回0
{
	assert(ps);
	return ps->top == 0;//代码简洁
}

1.5主函数实现
#include"Stack.h"
void Stacktest()
{
	Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	StackPush(&st, 5);
	while (!StackEmpty(&st))
	{
		cout << StackTop(&st) << ' ';
		StackPop(&st);
	}   //符合栈的性质,相对而言的后进先出(相对于栈里的数据)
	StackDestory(&st);
}
int main()
{
	Stacktest();
}

入栈顺序:12345,出栈顺序:54321

2.队列 2.1队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列中数据遵守先进先出FIFO(First In First Out)原则。入队列:进行插入操作的一端称为队尾,出队列:进行删除操作的一端称为队头

2.2队列的实现

数组和链表都能实现队列。但FIFO的特点使得数组实现效率很低,内存浪费。而链表的结构更加优秀。用两个指针分别指向队列的队头和队尾(初始状态如图a)入队出队的过程其实就是无头单向链表的实现(头插和尾删),具体请看:(99条消息) C/C++【数据结构笔记】(顺序表&链表)(超详细总结和细节)_Answer-2296的博客-CSDN博客)

2.3队列头文件
#pragma once
#include
#include
using namespace std;
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;//无头单向链表的结点

struct Queue 
{
	//用这个结构体来代表队列
	QNode* head;//指向队列的头
	QNode* tail;//指向队列的尾
};
//队列初始化
void QueueInit(Queue* qp);
//销毁队列
void QueueDestory(Queue* qp);
//入队(队尾入队)
void QueuePush(Queue* qp,QDataType x);
//出队(队头出队)
void QueuePop(Queue* qp);
// 获取队列头部元素
QDataType QueueFront(Queue* qp);
// 获取队列队尾元素
QDataType QueueBack(Queue* qp); 
// 获取队列中有效元素个数
int QueueSize(Queue* qp);
// 检测队列是否为空,如果为空返回1,如果非空返回0
bool QueueEmpty(Queue* qp);
2.4队列源文件
#pragma once
#include"Queue.h"

void QueueInit(Queue* qp)//队列初始化
{
	assert(qp);
	qp->head = qp->tail = NULL;//初始化都置成空!
}

void QueueDestory(Queue* qp)//销毁队列
{
	assert(qp);
	QNode* cur = qp->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}//逐个销毁
	qp->head = qp->tail = NULL;//没用的指针都置成空,避免野指针
}

void QueuePush(Queue* qp, QDataType x)//入队(队尾入队)
{
	assert(qp);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (!newnode)
	{
		cout << "malloc failed";
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;//构建好数据结点
	if (qp->tail == NULL)
	{
		qp->head = qp->tail = newnode;
		//如果是空队列,队尾队头都要变
	}
	else
	{
		qp->tail->next = newnode;
		qp->tail = newnode;//重新改变队尾
	}
}

void QueuePop(Queue* qp)//出队(队头出队)
{
	assert(qp);
	assert(qp->head);//队列非空才能出队
	if (qp->head->next == NULL)
	{
		free(qp->head);
		qp->head = qp->tail = NULL;
	}//队列只有一个结点,则置空队列(qp->tail=NULL)如果没单独考虑,qp->tail会成为野指针。
	else
	{
		QNode* next = qp->head->next;
		free(qp->head);
		qp->head = next;
	}
}

QDataType QueueFront(Queue* qp)// 获取队列头部元素
{
	assert(qp);
	assert(qp->head);
	return qp->head->data;
}

QDataType QueueBack(Queue* qp)// 获取队列队尾元素
{
	assert(qp);
	assert(qp->head);
	return qp->tail->data;
}

int QueueSize(Queue* qp)// 获取队列中有效元素个数
{
	assert(qp);
	int size = 0;
	QNode* cur = qp->head;
	while (cur)
	{
		size++;
		cur = cur->next;
	}
	return size;
}

bool QueueEmpty(Queue* qp)// 检测队列是否为空,如果为空返回1,如果非空返回0
{
	assert(qp);
	return qp->head == NULL;//简洁!
}
2.5主函数实现
#include"Queue.h"
void Queuetest()
{
	Queue  q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	while (!QueueEmpty(&q))
	{
		cout << QueueFront(&q) << " ";
		QueuePop(&q);//输出完删除,模拟栈出过程
	}
}
int main()
{
	Queuetest();
}

队列入队顺序12345,出队顺序12345

2.6环形队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列可以使用数组,实现,也可以使用链表实现。

栈和队列区别与联系

栈中的数据元素遵守后进先出***LIFO(Last In First Out)***的原则。并且是相对而言,多为后进先出是指,栈现有的数据是后进先出,所以可以出现先进栈的数据比后进栈的数据先出(比如数据进栈立马出栈,这时它就比后面数据先出来,所以说栈的后进先出是相对而言的)

队列中数据遵守先进先出FIFO(First In First Out)原则。并且是绝对而言,只要是先进队列的一定是先出来的。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/920331.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号