c语言实现栈和队列

栈的概念

栈是一个特殊的线性表,只允许在固定的一头进行操作,进行数据插入和删除的一头为栈顶,另一端为栈底。即入数据在栈顶,出数据也在栈顶。

栈的结构如图

栈的实现

那么栈可以用什么结构去实现呢?

其实用数组和链表去实现都可以,最佳方案用数组更好,因为数组在尾部进行尾插尾删还是很方便的,唯一缺点就是增容有空间浪费。如果用链表实现栈,插入删除数据会不方便,如果用尾做栈顶,尾加尾删会不方便,如果用尾做栈底,那么栈的插入删除就是链表的头插头删,也是可以实现栈的。

总结一下就是两种结构实现都可以,数组缓存利用率更高,数组栈稍好

头文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>//没引用这个头文件导致开辟形空间失败
#include<stdbool.h>
typedef int LTDataType;
typedef struct Stack
{
	LTDataType* a;
	int top;
	int capacity;
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps,LTDataType x);
void StackPop(ST* ps);
LTDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);

头文件的引入不要掉了,我当时就是忘记引入stdlib.h导致后面写入数据时发生了内存错误,非常难找错误

初始化

void StackInit(ST* pa)
{
	assert(pa);
	pa->a = NULL;
	pa->top = 0;
	pa->capacity= 0;

}

销毁

void StackDestory(ST* pa)
{
	assert(pa);
	free(pa->a);//不是freepa
	pa->a = NULL;
	pa->top = 0;
	pa->capacity = 0;
}

pa是指针,要访问结构体指针就要用->访问

入栈

void StackPush(ST* pa,LTDataType x)
{
	assert(pa);
	//不知道怎么开辟新空间和将新空间判断给值
	if (pa->top == pa->capacity)
	{
		int newcapacity =pa->capacity == 0 ? 4 : pa->capacity * 2;
		LTDataType* tmp = realloc(pa->a,newcapacity*sizeof(LTDataType));
		if (tmp == NULL)
		{
			printf("realloc fail");
			exit(-1);
		}
pa->a = tmp;
	pa->capacity = newcapacity;
}
	pa->a[pa->top] = x;
	pa->top++;
	}

出栈

void StackPop(ST* pa)
{
	assert(pa);
	assert(pa->top);
	//总感觉掉个条件
	pa->top--;
}

当栈为空就不能删除了

栈顶

LTDataType StackTop(ST* pa)
{
	assert(pa);
	assert(pa->top > 0);
	//return pa->top;
	return pa->a[pa->top - 1];
}

因为初始化栈顶一开始为0,这时top指向栈顶数据的下一个

判断空

bool StackEmpty(ST* pa)
{

	return pa->top ==0;
}

大小

int StackSize(ST* pa)
{
	assert(pa);
	return pa->top;
}

打印

while (!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}

因为只能找到栈顶的数据,所以只能找到一个打印一个然后删除栈顶

队列的概念

只允许一端进另一端出的特殊线性表,具有先进先出的特性

结构如图

那么队列用什么实现比较好呢?

如果用数组去实现,当出数据时就要遍历整个结构去挪动数据,显然不方便

所以我们用链表实现,因为每次都要找尾,所以我们定义一个尾指针,那为什么单链表不也引用尾指针呢?当我们在单链表引入尾指针可以解决尾加,,但是解决不了尾删,既然解决不了所有问题,那么我们就把这个问题给了双向循环链表去解决

头文件

#pragma once 
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QueueNode;
typedef struct Queue
{
	QueueNode* head;
	QueueNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
void QueuePush(Queue* pq,QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);

初始化

void QueueInit(Queue* pq)
{
	pq->head = NULL;
	pq->tail = NULL;
}

初始化的是头尾的指针

销毁

void QueueDestory(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
}

插入

void QueuePush(Queue* pq,QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	newnode->data = x;
	newnode->next = NULL;
	/*QueueNode* cur = pq->head;
	while(cur)
	{
		cur = cur->next;
	}
	cur->next = newnode;
	不用定义额外指针结构包含了头指针和尾指针*/
	if (pq->head == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

删除

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	QueueNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}

}

要注意如果头指针为空,第一个表达式就错了,当删到最后一个头指针时,如果不将尾指针置空,那么尾指针就指向一个不知道的空间,造成野指针

头指针的数据

QDataType QueueFront(Queue* pq)
{
	return pq->head->data;
}

尾指针的数据

QDataType QueueBack(Queue* pq)
{
	return pq->tail->data;
}

打印

while (!QueueEmpty(&q))
	{
		QDataType Front = QueueFront(&q);
		printf("%d ", Front);
		QueuePop(&q);
	}

从头出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值