队列

队列

1.基本概念及描述

队列也是一种特殊的线性表,队列的插入和删除在表的两端进行,插入的那端称为队尾,删除的那端叫做队首,插入和删除操作分别叫做进队出队

生活中的排队购票现象就是队列的例子,先到先享受,队列具有“先进先出”(First In First Out)的特点.

2.顺序队列及其实现

C语言中,顺序队列可以使用一维数组来表示。使用两个指针front和rear来标识队首和队尾,front指的是队列最前面,即队首结点在数组元素的下标;rear指的是队尾元素在数组元素下标中的下一个位置,就是即将插入元素的元素在数组中对应的下标。

typedef int datatype;
typedef struct
{
	datatype* a;
	int capacity;
	int front;//指向队首
	int rear;//指向队尾元素的下一个数组的下标
}queue;

2.1 基本操作

(1)初始化和销毁

void Init(queue* sq)
{
	sq->a = NULL;
	sq->capacity = 0;
	sq->front = sq->rear = 0;
}

void Destroy(queue* sq)
{
	if (sq)
	{
		free(sq->a);
		sq->a = NULL;
		sq->capacity = 0;
		sq->front = sq->rear = 0;
	}
}

(2)获得队首元素的值

datatype Get(queue sq)
{
	assert(&sq);
	return sq.a[sq.front];
}

(3)插入

void Insert(queue* sq,datatype x)
{
	assert(sq);
	if (sq->capacity == sq->rear)//扩容
	{
		int newcapacity = sq->capacity == 0 ? 4 : 2 * sq->capacity;
		datatype* tmp = (datatype*)realloc(sq->a, newcapacity * sizeof(datatype*)+1);
		if (tmp == NULL)
		{
			perror("realloc fail");
		}
		sq->a = tmp;
		sq->capacity = newcapacity;
	}
	sq->a[sq->rear++] = x;
}

(4)删除

void Dele(queue* sq)
{
	assert(sq);
	sq->front++;
}

3.顺序循环队列及其实现

一个队列经过若干次的插入和删除后,数组的前部可能还有空闲的位置,有空间的浪费。为了有效利用空间,可以将队列想象为一个环状,将数组最前的最后想象为是相邻的,这就是循环队列

再(b)状态中,如果再插入一个新的结点,数组空间就会被全部占用,此时frontrear,er再状态(c)中,删除一个结点后,也有frontrear,这两种情况条件都相同,如何解决呢?

(1)方法一:

设置一个标志,标识是由于rear增1使得frontrear,还是front增1使得frontrear,前者是队满后者是队空。

(2)方法二:

牺牲一个数组元素的空间,若数组的大小为MAXSIZE,数组最多存MAXSIZE-1个结点。

队满的条件:(rear+1)%MAXSIZE=front;

队空的条件:rear=front;

这里我们实现第一种

3.1 基本操作

(1)插入

void Insert(queue*sq,datatype x)
{
	if(sq->rear+1%MAXSIZE==sq->front)
    {
        printf("队列已满,进行扩容!");
        ……
    }
    sq->a[sq->rear]=x;
    sq->rear=(sq->rear+1)%MAXSIZE;
}

(2)删除

void Dele(queue*sq)
{
    if(sq->front==sq->rear)
    {
        printf("循环队列是空的,无法操作!!!");
        exit(1);
    }
    sq->front=(sq->front+1)%MAXSIZE;
}
posted @ 2024-08-22 22:21  kio鱼  阅读(28)  评论(0编辑  收藏  举报