数据结构:第3讲:栈与队列

目录

1.栈的定义与实现

2.队列的定义与实现

3.栈与队列的应用


1.栈的定义与实现

(1)定义:

栈(stack) 是限定仅在表尾进行插入或删除操作的线性表。因此对栈来说,表尾端有其特殊含义,称为 栈顶(top) ,相应的,表头端称为 栈底(bottom) 。不含元素的空表称为 空栈

注:栈是限制插入和删除操作只能在一个位置进行的表,该位置是表的末端,叫作栈顶。对栈的基本操作有 进栈(push)出栈(Pop),前者相当于插入,后者则是删除最后插入的元素。

(2)栈的顺序结构

①结构实现

top 用来保存栈顶元素的下标值。

②初始化

最开始的时候是空栈,所以不能让top等于0,等于0意味着在第0个位置已经有元素了。

③判断栈是否为空

④进栈 / 压栈

⑤出栈

出栈并没有真正删除了栈顶元素(即无内存释放),该元素还在原来的位置,只是改变了下标。

⑥获取栈顶元素

⑦利用动态内存分配来初始化

(3)栈的链式结构

注:链式栈中栈顶在链表头。

①结构实现

②初始化

③判断栈是否为空

方法:看头节点的next是不是为空。

④进栈 / 压栈

进栈时新建结点插在链表最前面。

⑤出栈

⑥获取栈顶元素

2.队列的定义与实现

(1)定义:

(2)队列的顺序结构

①结构实现:

front 保存的是队头元素的下标值,rear 保存的是队尾元素的下一个元素的下标值。

②初始化:

③判断当前队列是否为空:

队头等于队尾,即可说明队列为空。

④出队:

出队是指从队头删掉一个元素。

c 复制代码
int dequeue(Queue* Q, ElemType* e)
{
	if (Q->front == Q->rear)
	{
		printf("空的\n");
		return 0;
	}
	*e = Q->data[Q->front];
	Q->front++;
	return 1;
}

⑤调整队列:

  • 需要调整队列的情况:

当rear大于等于MAXSIZE时,但前面还有空余,此时rear这个位置无法再继续添加新数据了。要调整队列才可以继续添加新数据。

注:rear大于等于MAXSIZE时,队列不一定存满。

  • 代码实现:
c 复制代码
int queueFull(Queue* Q)
{
	if (Q->front > 0)
	{
		int step = Q->front;
		for (int i = Q->front; i < Q->rear; i++)
		{
			Q->data[i - step] = Q->data[i];
		}
		Q->front = 0;
		Q->rear = Q->rear - step;
		return 1;
	}
	else
	{
		printf("真的满了\n");
		return 0;
	}
}

⑥入队:

注:队列的顺序结构中,如果该队列刚好存满时,rear 等于 MAXSIZE。

⑦获取队头数据

⑧动态内存分配来初始化

⑨循环队列

  • 入队

a.代码实现

注:满队列判断:(rear+1)%MAXSIZE == front。队尾往后移动一步:(rear+1)%MAXSIZE。

b.注意事项

此时这个状态已经是满队列状态了,就是要留一个空,利用满队列判断的公式即可判断。

  • 出队

(3)队列的链式结构

①结构:

front总是指向头结点,rear总是指向尾结点。

②初始化:

③判断队列是否为空:

④入队:

利用尾插法来入队。

⑤出队:

  • 出队是删除头结点的下一个结点,有一种特殊的场景:

要删除的是尾结点,删除之后还要让front和rear都指向头结点。

  • 代码实现:

⑥获取队头元素:

(4)双端队列

两头都能出,都能入。

3.栈与队列的应用

(1)

解析:

出队的顺序是 bdcfeag,可以推出该队列的顺序是 gaefcdb。队列中,ab先进来,b出去。cd进来,dc出去。ef进来,fe出去。a出去。g进来,g出去。

(2)

(3)

解析:p1的取值有1,2,4三种可能,p3除了3不可能取到,其余都有可能性,所以n - 1。

(4)