栈和队列(数据结构)

你好,我是史丰源
欢迎你的来访,希望我的博客能给你带来一些帮助。

我的Gitee:代码仓库.☀️

我的联系方式:
QQ:1756786195
邮箱:Marksky126@outlook.com🌐

一、栈的简介(栈不支持遍历)

栈:是一种特殊的线性表,它只允许在一端进行删除和插入(栈顶),插入删除端叫做栈顶,而另一端叫做栈底。
栈中元素遵循 “后进先出” LIFO(Last in first out)原则.

栈的实现

栈可以用数组实现,也可以用链表实现。
这里我们使用数组实现栈栈示例

typedef struct Stack//定义一个栈
{
	StaType* a;//动态数组地址
	int top;//栈顶,相当于顺序表中的size
	int capacity;//栈容量
}Stack;

从结构就可知,栈和顺序表的结构极其相似,所以我们可以根据顺序表的操作直接进行编写。

栈的初始化
void StackInit(Stack* ST)
{
	assert(ST);
	ST->a = NULL;
	ST->top = 0;
	ST->capacity = 0;
}
栈的销毁(与初始化相比,多了一个释放)
void StackDestory(Stack* ST)
{
	assert(ST);
	free(ST->a);
	ST->a = NULL;
	ST->top = 0;
	ST->capacity = 0;
}
入栈
void StackPush(Stack* ST, StaType x)
{
	assert(ST);
	if (ST->top == ST->capacity)//空间满了
	{
		int newcapacity = ST->capacity == 0 ? 4 : ST->capacity * 2;//新的容量
		StaType* tmp = (StaType)realloc(ST->capacity,sizeof(StaType)*newcapacity);//数组扩容

		if (tmp == NULL)
		{
			printf("realloc fail");
			exit(-1);
		}
		ST->a = tmp;
		ST->capacity = newcapacity;
	}

		ST->a[ST->top] = x;//在栈顶插入元素
		ST->top++;//栈顶+1

}
栈的判空
bool StackEmpty(Stack* ST)
{
	assert(ST);
	return ST->top == 0;//如果是0就true,非0-false
	//也可自己判断if(ST->top == 0),上面这种结构大大简化代码量
}
出栈
void StackPop(Stack* ST)
{
	assert(ST);
	assert(!StackEmpty(ST));//栈的判空,如果是空的栈,无法删除,直接报错
	ST->top--;//把栈顶指针向下移动一位,移到向下一个结点
}
返回栈顶元素
StaType StackGet_Top(Stack* ST)//返回的是一个数据(元素)
{
	assert(ST);
	assert(!StackEmpty(ST));
	return ST->a[ST->top-1];//top指的是栈顶的下一个位置
	//top现在指的位置为空,所以要减一。
}

注意:栈中的元素范围:0~top-1,而出栈和入栈的操作是top的相对增减.

如图:我要出栈7这个元素,第一次top是在7上面的空间,7在top-1的空间,我执行出栈动作:

ST->top--;

7的位置变成top,如果我再插入数据,执行的是入栈操作

ST->a[ST->top] = x;

所以我就把7这个元素给覆盖了
top解释

二、队列的简介(队列不支持遍历)

队列:也是一种特殊的顺序表,在队尾插入数据,队头删除数据,遵循 先进先出 FIFO(First in First out)原则。
其适合使用链表进行实现,入队:尾插。出队:头删。

队列实现

队列的定义
typedef int  QType;//注意这里写typedef而不是define.

typedef struct QueueNode//结点定义,与单链表实现一致
{
	QType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* head;//记录队头结点,记住这里是QNode
	QNode* tail;//记录队尾结点
}Queue;

队列的初始化
void InitQueue(Queue* p)
{
	assert(p);
	p->head = p->tail = NULL;
}
队列的销毁
void DestoryQueue(Queue* p)
{
	assert(p);
	assert(!QueueEmpty(p));
	free(p->head);
	free(p->tail);
	p->head = p->tail = NULL;
}
入队
void PushQueue(Queue* p, QType x)
{
	assert(p);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;

	if (p->head == NULL)
	{
		p->head = p->tail = newnode;//第一次
	}

	else
	{
		p->tail->next = newnode;//尾插
		p->tail = newnode;
	}
}
出队
void PopQueue(Queue* p)//头删呗
{
	assert(p);
	assert(!QueueEmpty(p));

	if (p->head->next == NULL)//只有一个结点
	{
	free(p->head);
	p->head = p->tail = NULL;
	}
	else
	{
	QNode* next = p->head->next;
	free(p->head);
	p->head = next;
	}
}
返回队头队尾元素
QType QueueFront(Queue* p)
{
	assert(p);
	return p->head->data;
}

QType QueueBack(Queue* p)
{
	assert(p);
	return p->tail->data;
}
队列的长度(也可直接在结构体中定义一个size)
int QueueSize(Queue* p)
{
	QNode* cur = p->head;
	int size = 0;
	while (cur)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

队列判空
bool QueueEmpty(Queue* p)
{
	if (p->head == NULL)
	{
		return p->head == NULL;
	}
}

总结:栈与队列都是特殊的线性表,其结构也与数组与单链表极其相似,我们需记住它们插入与删除的特殊方式,与顺序表加以区分,便可掌握。

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值