前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >栈和队列(C语言实现)

栈和队列(C语言实现)

作者头像
有礼貌的灰绅士
发布2023-03-28 15:20:37
8870
发布2023-03-28 15:20:37
举报
文章被收录于专栏:C++与Linux的学习之路

栈和队列

分析

栈的数据是栈顶进,栈顶出。 我们用数组和链表都可以,但是链表因为尾插和尾删没有数组方便,所以我们用数组。

在这里插入图片描述
在这里插入图片描述

例子:如果进去的顺序是1234,出来的顺序就是4321。 我们可以用一个数组来储存数据,然后再定义一个指针指向栈顶的数据,方便出栈和入栈。

代码语言:javascript
复制
typedef int SD;//随时更改数据类型
typedef struct stack
{
	SD* a;//数组
	int top;//栈顶的后一个位置
	int capacity;//容量
}ST;

这里用指针定义的数组,后面我们可以用扩容增加容量,这样就变成了一个数组。

初始化与销毁栈

一定要初始化空间,不然容易造成野指针的问题。 初始化

代码语言:javascript
复制
void StackInit(ST* ps)//初始化
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

初始化就不开辟空间了。 销毁栈 这里和链表不一样,比较方便,释放掉起始地址就好了。

代码语言:javascript
复制
void StackDestroy(ST* ps)//销毁栈
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

出栈入栈与判断栈为空

入栈

代码语言:javascript
复制
void StackPush(ST* ps, SD x)//入栈
{
	assert(ps);
	//扩容
	if (ps->capacity == ps->top)//判断是否需要扩容
	{
		int count = (ps->capacity == 0 ? ps->capacity = 4 : ps->capacity * 2);//第一次扩容4个,之后的扩容的容量二倍增加
		SD* y = (SD*)realloc(ps->a, count * sizeof(SD));
		 if (y == NULL)
		 {
			 perror("realloc fail");
			 exit(-1);
		 }
		 ps->a = y;
		 ps->capacity = count;
	}
	ps->a[ps->top] = x;//赋值
	ps->top++;
}

例:

在这里插入图片描述
在这里插入图片描述

此时的top是4. 判断栈是否为空

代码语言:javascript
复制
bool StackEmpty(ST* ps)//判断
{
	assert(ps);
	return ps->top == 0;//如果为空就返回1,不为空返回0
}

出栈

代码语言:javascript
复制
void StackPop(ST* ps)//出栈
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

出栈就很简单了,因为top是末尾的数据,如果想再入栈,入栈的地方是top指向的地方,会覆盖掉原来的数据。

获取栈顶元素

代码语言:javascript
复制
SD StackTop(ST* ps)//获取栈顶元素
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top - 1];
}

获取栈中有效元素个数

top也就等于栈中数据的数量。

代码语言:javascript
复制
int StackSize(ST* ps)//获取栈中有效的元素
{
	assert(ps);
	return ps->top;
}

队列

分析

队列是从队头出,队尾入,数组就没有链表好用了,所以我们用单向链表。

在这里插入图片描述
在这里插入图片描述

结点

代码语言:javascript
复制
typedef int SD;
typedef struct QListNode
{
	struct QListNode* next;
	SD data;
}QL;

因为我们需要的是头删尾插,所以不仅仅需要头结点,还需要一个尾结点,这样更方便操作。

代码语言:javascript
复制
typedef struct Queue
{
	QL* head;//头结点,指向队列的队头
	QL* tail;//尾结点,指向队列的队尾
	int siz;//计算有多少个结点
}Qu;

初始化与销毁队列

初始化 头结点和尾结点的指向空即可,siz初始化为0用来记录结点数量。

代码语言:javascript
复制
void QueueInit(Qu* q)//初始化
{
	assert(q);
	q->head = q->tail = NULL;
	q->siz = 0;
}

销毁队列

代码语言:javascript
复制
void QueueDestroy(Qu* q)//销毁队列 
{
	assert(q);
	QL* cur = q->head;//这里要注意数据类型
	while (cur)
	{
		QL* del = cur -> next;
		free(cur);
		cur = del;
	}
	q->head = q->tail = NULL;
	q->siz = 0;
}

入列,出列与判断队列是否为空

入列 这里需要考虑队列是否为空的尾插。

代码语言:javascript
复制
void QueuePush(Qu* q, SD x)//入队
{
	assert(q);
	QL* w = (QL*)malloc(sizeof(QL));//新开辟结点
	if (w == NULL)
	{
		perror("malloc tail");
		exit(-1);
	}
	else
	{
		w->data = x;
		w->next = NULL;
	}
	if (q->head == NULL)//如果队列为空
	{
		q->head = q->tail = w;
	}
	else//如果队列不为空
	{
		q->tail->next = w;
		q->tail = w;
	}
	q->siz++;
}

判断 不为空返回0,为空返回非零。

代码语言:javascript
复制
bool QueueEmpty(Qu* q)//判断
{
	assert(q);
	return q->head == NULL;
}

出列 这里就是典型的头删了,只不过需要注意的是,tail是不会在这个函数中移动的,所以当释放掉tail指向的结点时,要把tail置为空,不然会成为野指针。

代码语言:javascript
复制
void QueuePop(Qu* q)//出队
{
	assert(q);
	assert(!QueueEmpty(q));
	if (q->head == NULL)//防止tail成为野指针
	{
		free(q->head);
		q->head = q->tail = NULL;
	}
	QL* cur = q->head;
	q->head = q->head->next;
	free(cur);
	cur = NULL;
	q->siz--;
}

获取队列头部,尾部元素

这里就体现了head和tail的好处。 头部

代码语言:javascript
复制
SD QueueFront(Qu* q)//获取队头元素
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->head->data;
}

尾部

代码语言:javascript
复制
SD QueueBack(Qu* q)//获取队尾元素
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->tail->data;
}

获取队列中有效元素个数

直接返回之前用于记录数量的siz就可以了。

代码语言:javascript
复制
int QueueSize(Qu* q)//获取队列中有效元素个数
{
	assert(q);
	return q->siz;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 栈和队列
    • 分析
      • 初始化与销毁栈
        • 出栈入栈与判断栈为空
          • 获取栈顶元素
            • 获取栈中有效元素个数
            • 队列
              • 分析
                • 初始化与销毁队列
                  • 入列,出列与判断队列是否为空
                    • 获取队列头部,尾部元素
                      • 获取队列中有效元素个数
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档