栈和队列(C语言)

目录

数据结构之栈

定义

实现方式

基本功能实现

1)定义,初始化栈

2)入栈

3)出栈

4)获得栈顶元素

5)获得栈中有效元素个数获得栈中有效元素个数)

6)检测栈是否为空

7)销毁栈

数据结构之队列

定义

实现方式

基本功能实现

1)定义,初始化队列

2)入队

3)出队

4)获得队列头部元素

5)获得队尾元素

6)队列元素个数

7)队列是否为空

8)销毁队列

栈和队列练习

[1.1 有效括号](#1.1 有效括号)

用栈的先入后出性质


数据结构之栈

定义

栈:一种特殊的线性表,其特点是只允许在一端进行插入和删除的操作,这一端叫做栈顶,另一端叫做栈底;栈中的数据使用的时候必须遵行先入后出(先进入的后出来)的原则。++就好比一群人上电梯,最先进去的站在里面,最后出来,而最后上来的站在门口,最先出来。++

压栈:向栈顶插入元素;

出栈:将栈顶元素删去;

原则:入栈和出栈的操作对象都是栈顶。

实现方式

栈的实现方式有两种,可以用前面的顺序表也可以使用链表。

1)使用链表实现,要记录尾节点(避免遍历链表找尾)方便压栈;同时还要记录倒数第二个节点,方便出栈时,将尾节点释放。所以一共需要定义两个结构体:链表结构体,结构体(记录头节点,尾节点,倒数第二个节点);

2)使用顺序表实现,顺序表有栈内的总个数,可以直接找到尾,也可以直接出栈,相比于链表更简单。所以我们更推荐使用顺序表来实现栈。

顺序表(含通讯录)-CSDN博客文章浏览阅读743次,点赞16次,收藏11次。C语言实现顺序表及其基本功能的实现,包含通讯录项目。https://blog.csdn.net/2401_87944878/article/details/144408098https://blog.csdn.net/2401_87944878/article/details/144408098https://blog.csdn.net/2401_87944878/article/details/144408098https://blog.csdn.net/2401_87944878/article/details/144408098https://blog.csdn.net/2401_87944878/article/details/144408098https://blog.csdn.net/2401_87944878/article/details/144408098https://blog.csdn.net/2401_87944878/article/details/144408098

链表(C语言)-CSDN博客文章浏览阅读730次,点赞18次,收藏7次。用C语言实现数据结构中单链表和双链表的详细介绍https://blog.csdn.net/2401_87944878/article/details/144423576https://blog.csdn.net/2401_87944878/article/details/144423576https://blog.csdn.net/2401_87944878/article/details/144423576https://blog.csdn.net/2401_87944878/article/details/144423576https://blog.csdn.net/2401_87944878/article/details/144423576https://blog.csdn.net/2401_87944878/article/details/144423576https://blog.csdn.net/2401_87944878/article/details/144423576

基本功能实现

1)定义,初始化栈

栈的底层逻辑是顺序表,所以可以直接使用顺序表的初始化。

cpp 复制代码
typedef int SDateType;

typedef struct Stack
{
	SDateType* a;
	int size;
	int capacity;
}Stack;

//栈的初始化
void StackInit(Stack* ps)
{
    assert(ps);
	ps->capacity = 4;
	ps->a = (SDateType*)malloc(sizeof(SDateType)*(ps->capacity));
	if (ps->a == NULL)
		perror("malloc failed!");

	ps->size = 0;
}

2)入栈

向栈顶添加元素,ps->size就是栈顶位置的下标;

cpp 复制代码
//入栈
void StackPush(Stack* ps,  SDateType x)
{
    assert(ps);
	//判断空间够不够
	if (ps->capacity == ps->size)
	{
		ps->capacity *= 2;
		SDateType* new = (SDateType*)realloc(ps->a,sizeof(SDateType) * (ps->capacity));
		if (new == NULL)
			perror("realloc failed!");

		ps->a = new;
	}
	//入栈
	ps->a[ps->size] = x;
	ps->size++;
}

3)出栈

出栈不需要对栈顶元素进行处理,只需要将栈内元素个数-1即可,将栈顶元素看作无效数据;

cpp 复制代码
//出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->size);

	ps->size--;
}

4)获得栈顶元素

cpp 复制代码
//获得栈顶元素
SDateType StackTop(Stack* ps)
{
	assert(ps->a);
	assert(ps->size);

	return ps->a[ps->size - 1];
}

5)获得栈中有效元素个数

cpp 复制代码
//获得栈中有效元素个数
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->size;
}

6)检测栈是否为空

cpp 复制代码
//检测栈是否为空
bool IsStackEmpty(Stack* ps)
{
	assert(ps);
	if (ps->size == 0)
		return true;

	return false;
}

7)销毁栈

将malloc的空间释放,将顺序表中的变量制空。

cpp 复制代码
//栈的销毁
void StackDestory(Stack* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

数据结构之队列

定义

队列:也是一种特殊的线性表,其特点是只允许在一端(队尾)进行插入,另一端(队头)进行删除。队列的数据结构必须遵循先入先出(先进入的先出来原则。++就好比车辆进站加油,先进入的车会先出来。++

入队:向队尾添加元素;

出队:将队头的元素删去;

实现方式

与栈相同,队列也有两种实现方式;

1)顺序表实现,用顺序表可以直接找到队尾,进行入队,但是在出队的时候将队头元素删除后,要将后面元素整体向前移动,效率低。

2)链表实现,用链表实现的时候,只要记录了尾节点,头节点就可以直接对队列进行入队和出队操作,链表实现的效率更高,此处以链表实行为例。

基本功能实现

1)定义,初始化队列

++定义两个结构体,1)链表;2)用于记录头节点,尾节点及链表长度的结构体。++

cpp 复制代码
//定义队列
typedef int QDateType;

typedef struct QueNode
{
	QDateType date;
	struct QueNode* next;
}QueNode;

typedef struct Queue
{
	QueNode* front;
	QueNode* tail;
	int size;
}Queue;



//队列的初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->front = pq->tail = NULL;
	
	pq->size = 0;
}

2)入队

向队尾添加元素;

cpp 复制代码
//入队
void QueuePush(Queue* pq, QDateType x)
{
    assert(pq);
	//创建新节点
	QueNode* newnode = (QueNode*)malloc(sizeof(QueNode));
	newnode->date = x;
	newnode->next = NULL;

	if (pq->front == NULL)
		pq->front = pq->tail = newnode;
	else
	{
		pq->tail->next = newnode;
		pq->tail = pq->tail->next;
	}
}

3)出队

将队头元素删去。

cpp 复制代码
//出队
void QueuePop(Queue* pq)
{
    assert(pq);
	//记录队头
	QueNode* del = pq->front;
	pq->front = pq->front->next;

	free(del);
	del = NULL;
}

4)获得队列头部元素

cpp 复制代码
//获得队列头部元素
QDateType QueTop(Queue* pq)
{
	assert(pq);
	assert(pq->size);

	return pq->front->date;
}

5)获得队尾元素

cpp 复制代码
//获得队尾元素
QDateType QueTail(Queue* pq)
{
	assert(pq);
	assert(pq->size);

	return pq->tail->date;
}

6)队列元素个数

cpp 复制代码
//获得队列元素个数
int QueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

7)队列是否为空

cpp 复制代码
//判断队列是否为空
bool IsQueueEmpty(Queue* pq)
{
	assert(pq);
	if (pq->size == 0)
		return true;

	return false;
}

8)销毁队列

cpp 复制代码
//销毁队列
void QueDestory(Queue* pq)
{
	assert(pq);
	//要销毁队列的每一个元素
	while (!IsQueueEmpty)
	{
		QueuePop(pq);
	}
	pq->front = pq->size = NULL;
}

栈和队列练习

1.1 有效括号

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

用栈的先入后出性质

遍历字符串,对于左括号入栈,当遇到右括号的时候,出栈,将出栈元素和左括号进行对比,看是否配对。

cpp 复制代码
//有效括号
bool isValid(char* s) {
	Stack sta;
	StackInit(&sta);

	char* cur = s;
	while(*cur!='\0')
	{
		//判断是否是左括号
		if ((*cur) == '(' || (*cur) == '{' || (*cur) == '[')
		{
			StackPush(&sta, *cur);
			cur++;
		}
		//将左括号和右括号进行对比
		else
		{
			if (IsStackEmpty(&sta))
				return false;

			char left = StackTop(&sta);
			StackPop(&sta);  //取出栈顶元素
			if ((left == '(' && (*cur) != ')') ||
				(left == '{' && (*cur) != '}') ||
				(left == '[' && (*cur) != ']'))
				return false;

			cur++;
		}
	}
	if(!IsStackEmpty(&sta))
		return false;   //栈中还有元素

	return true;
}
相关推荐
小黄人软件13 分钟前
C# ini文件全自动界面配置:打开界面时读ini配置到界面各控件,界面上的控件根据ini文件内容自动生成,点保存时把界面各控件的值写到ini里。
开发语言·c#
二进制人工智能1 小时前
【QT5 网络编程示例】TCP 通信
网络·c++·qt·tcp/ip
Android洋芋3 小时前
C语言深度解析:从零到系统级开发的完整指南
c语言·开发语言·stm32·条件语句·循环语句·结构体与联合体·指针基础
bjxiaxueliang3 小时前
一文详解QT环境搭建:Windows使用CLion配置QT开发环境
开发语言·windows·qt
莫有杯子的龙潭峡谷3 小时前
3.31 代码随想录第三十一天打卡
c++·算法
Run_Teenage3 小时前
C语言 【初始指针】【指针一】
c语言·开发语言
苹果.Python.八宝粥4 小时前
Python第七章02:文件读取的练习
开发语言·python
AaronZZH4 小时前
【进阶】vscode 中使用 cmake 编译调试 C++ 工程
c++·ide·vscode
我的sun&shine4 小时前
高级数据结构03RB树
数据结构·b树
J不A秃V头A4 小时前
Redis批量操作详解
开发语言·redis