栈和队列(数据结构)

栈和队列(数据结构),第1张

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

我的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这个元素给覆盖了

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

队列:也是一种特殊的顺序表,在队尾插入数据,队头删除数据,遵循 先进先出 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;
	}
}

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

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1294644.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-10
下一篇2022-06-10

发表评论

登录后才能评论

评论列表(0条)

    保存