“抽象”《大话数据结构》第四章——队

队的定义

队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列的抽象数据类型

数据部分:
线性表的数据元素同类型,相邻元素具有前驱和后驱关系
操作部分:
1 建立空队列
2 释放队列的存储空间
3 从队尾插入新的元素
4 从队头删除元素

队列的顺序存储结构

循环队列

循环队列其实就是队列的顺序存储结构,即元素在存储空间上是连续的。
定义front指针指向队头,rear指针指向队尾元素的的后一个空闲元素位置。
判断队列是否为空:
rear == front
判断队列是否队满:
为了区别于队空的判断条件,规定队满时,rear后面保留一个空闲元素。由于是循环队列,rear可能会大于front, 也有可能小于front,假设队列长度为SIZE。、

1 当front > rear时,若rear + 1 = front,即(rear + 1)% SIZE = front。
2 当rear > front时,唯一队满的情况就是front指向第一个,rear 指向倒数第二个。rear + 1 = SIZE,此时front 也指向下标为0的结点,故依然满足(rear + 1)% SIZE = front。

计算队列长度:
当front > rear时,队列长度分为两段,一段是SIZE - front,另一段是rear - 0,然后相加:rear - front + SIZE。
当rear > front时,队列长度就为rear - front。
为了统一公式:rear - front是二者共同点,(rear - front + SIZE)%SIZE

循环队列抽象数据类型实现

定义数据类型:
结构体需要数据域,需要记录队头的下标的front变量和记录队尾下标的rear变量。
代码如下:

#include 
#define SIZE  20
typedef int QElemType;
typedef struct
{
	QElemType data[SIZE];
	int front;
	int rear;
}

队列的初始化:
队列的初始化就是给队头front和队尾rear都赋0.
代码如下:

Status Init_Queue(Queue *init_queue)
{
	init_queue->front = 0;
	init_queue->rear = 0;
	return OK;
}

求队列长度:
就是利用公式(rear - front + SIZE)%SIZE
代码如下:

int obtain_longth(Queue *queue)
{
	return (queue->rear - queue->front + SIZE) % SIZE;
}

入队操作:

1 判断队满:(rear + 1)% SIZE = front
2 赋值给数据域
3 队尾后移一位(rear + 1)% SIZE
代码如下:

Status IN_Queue(Queue *in_queue, QElemType new_data)
{
	if((in_queue->rear +1 )%SIZE == in_queue->front)
		return ERROR;
	in_queue->data[in_queue->rear] = new_data;
	in_queue->rear = (in_queue->rear +1 )%SIZE;
	return ERROR;
}

出队操作:
1 判断队列是否为空:rear=front
2 把front的值赋给删除元素指针
3 front向后移动一位(front + 1)%SIZE
代码如下:

Status OUT_Queue(Queue *out_queue, QElemType *delete_data)
{
	if(out_queue->rear == out_queue->front)
		return ERROR;
	*delete_data = out_queue->data[out_queue->front];
	out_queue->front = (out_queue->front +1 )%SIZE;
	return ERROR;
}

队列的链式存储结构及实现

定义数据类型:
1 定义链表结点
2 定义存储队头、队尾指针的结构体,通过它,来操作队链表。

typedef struct Qnode
{
	QElemType data;
	struct Qnode *next;
	
}Qnode,*QUEUPTR;
typedef struct
{
	QUEUPTR front,rear;
}linkqueue;

入队操作:
1 rear->next = newnode。rear = newnode。rear->next = NULL。

Status IN_Link_Queue(linkqueue *PTR,QElemType new_data)
{
	QUEUPTR new_node;
	new_node = (QUEUPTR)malloc(sizeof(Qnode));
	if(!new_node)
		return ERROR;
	PTR->rear->next = new_node;
	PTR->rear = new_node;
	new_node ->data = new_data;
	new_node ->next = NULL;
	return OK;
}

出队操作:
1 判断链表是否为空,rear= front
2 delete_node = front,delete_node->data给删除数据指针,delete_node->next 赋值给front->next。
3 如果被删除的结点是队尾,则将尾指针指向头结点。
4 free(delete_node )
代码如下:

Status OUT_Link_Queue(linkqueue *PTR,QElemType *delete_data)
{
	QUEUPTR delete_node;
	if(PTR->front == PTR->rear)
		return ERROR;
	delete_node = PTR->front->next;
	*delete_data = delete_node->data;
	PTR->front->next = delete_node ->next;
	if(PTR->rear == delete_node)
		PTR->rear = PTR->front;
	free(delete_node);
	return OK;
}

你可能感兴趣的:(大话数据结构自学旅途)