数据结构(五)

队列

队列:只能选取一个端点进行插入操作,另一个端点进行删除操作的线性表。

队列的几个概念
队尾:进行插入的一端。
队首(队头):进行删除的一端。
进队(入队):向队列中插入新元素。
出队(离队):从队列中删除元素。

队列的主要特点:先进先出。

队列的基本运算
1、初始化队列。
2、销毁队列。
3、判断队列是否为空。
4、进队列。
5、出队列。

顺序队

一、非环形队列

顺序队的类型定义

typedef struct{
int data[MaxSize] //MaxSize表示数组的长度
int front,rear; //记录队首和队尾的
}SqQueue;

1、rear 总是记录队尾元素所在的数组下标
2、元素进队,rear增1
3、front指向当前队中队头元素的前一位置
4、元素出队,front增1
5、当rear=MaxSize-1时不能再进队

顺序队的四要素
1、队空条件:front =rear=-1
2、队满条件:rear=MaxSize-1
3、元素进队:rear++;data[rear]=e;
4、元素出队:front++;e=data[front];(把这个元素的值取给e)

1、初始化队列

void InitQueue(SqQueue *&q){
q=(SqQueue *)malloc(sizeof(SqQueue));
q->front=q->rear=-1;
} //构造一个空的队列;

2、销毁队列

void DestroyQueue(SqQueue *&q){
free(q);
} //释放掉q的空间

3、判断队列是否为空

bool QueueEmpty(SqQueue *q){
return (q->front==q->rear);
} //如果front==rear的话说明时空队列

4、进队列

bool enQueue(SqQueue *&q,int e){
if(q->rear==MaxSize-1){
return false;
} //判断是否队列已满
p->rear++;
p->data[rear]=e;
return true; //入队
}

5、出队列

bool deQueue(SqQueue *&q,int &e){
if(q->front==q->rear){
return false;
}
q->front++;
e=q->data[q->front]; //front是记录队首的前一个位置的
return true;
}

二、环形队列(循环队列)

假溢出:采用rear==MaxSize-1作为队满条件的话,可能在队满条件满足时,队中还有空出的位置。

解决假溢出的方案就是将队列设计成环形队列。

环形队列的四要素:
1、队空条件:front=rear;
2、队满条件:(rear+1)%MaxSize = front;
3、进队:rear=(rear+1)%MaxSize;data[rear]=e;
4、出队:front=(front+1)%MaxSize;e=data[front];

环形队列的队首,队尾,元素个数有着以下的关系:

count==(rear-front+MaxSize)%MaxSize;
rear==(front+count)%MaxSize;
front==(rear-count+MaxSize)%MaxSize;

所有,这三者知道其中任意两者可以求出剩余一者。(可以用元素个数代替队尾)

typedef struct{
int data[MaxSize];
int front;  //队头
int count;  //元素个数
}QuType; //此环形队列可最多放MaxSize个元素

1、环形队列的初始化

void InitQueue(QuType *&qu){
qu=(QuType*)malloc(sizeof(QuType));
qu->front=0;
qu->count=0;
}

2、环形队列的进队

bool EnQueue(QuType *&qu,int x){
int rear; //一个局部变量,qu中不保存的临时队尾
if(qu->count==MaxSize){
	return false; //判断是否队满
	}else{
	rear=(qu->front+qu->count)%MaxSize;//求队尾
	rear=(rear+1)%MaxSize;//做环形队列里的入队操作
	qu->data[rear]=x;
	qu->count++;//入队后元素数加一
	return true;
	}
}

3、环形队列的出队

bool DeQueue(QuType *&qu,int &x)
{if(qu->count==0){
	return false; //判断是否空队
	}else{
	qu->front=(qu->front+1)%MaxSize;
	x=qu->data[qu->front]; //做环形队列里的出队操作
	qu->count--; //元素数减一
	return true;
	}
}

4、循环队列判断是否队空

bool QueueEmpty(QuType *qu){
return (qu->count==0);
}

链队

链队:就是以链式存储结构为存储结构的队列。

链队中有两个部分,一个部分是链体本身,另一个是队首和队尾指针,所以来定义一个链队的类型。

typedef struct qnode{
int data;
struct qnode *next
}QNode; //链体

typedef struct{
QNode *front; //指向单链表的队头
QNode *rear; //指向单链表的队尾
}LiQueue;

链队的四要素:
1、队空条件:front=rear=NULL
2、队满条件:和链栈一样不考虑
3、进队:将元素插到单链表表尾
4、出队:删除单链表首数据节点

1、初始化链队

void InitQueue(LiQueue *&q){
q=(LiQueue *)malloc(sizeof(LiQueue));
q->front=q->rear=NULL;
}

2、销毁队列

void DestroyQueue(LiQueue *&q){
QNode *p=q->front,*r;
if(p!=NULL){
	r=p->next;
	while(r!=NULL){
    free(p);
    p=r;
    r=p->next;
			}
  		  }
  		 free(p); //释放掉单链表里的最后一个链节
  		 free(q);//释放掉队首队尾指针
}

3、判断队列是否为空

bool QueueEmpty(LiQueue *q){
return (q->rear==NULL);
}

4、进队

void enQueue(LiQueue*&q,int e){
QNode *p;
p=(QNode*)malloc(sizeof(QNode));
p->date=e;
p->next=NULL;
	if(q->rear==NULL){  //如果是空队列
	q->front=q->rear=p;
	}else{      //非空队列
     q->rear->next=p;
     q->rear=p;
	}
}

5、出队

bool deQueue(LiQueue *&q,int &e){
QNode *t;
if(q->rear==NULL){
   return false;   //空队的情况
   }
   t=q->front;
   if(q->front==q->rear){
   q->front=q->rear=NULL;  //只有一个节点的队列
	}else{
   q->front=q->front->next;//有多个节点
    }
    e=t->data;
    free(t);
    return true;
}

不带队首指针的链队

不带队首指针的链队,就是只有一个队尾的rear指针指着队尾,然后用队尾节点的指针指向队头。
简单来说就是把普通链队里的单链表变成了循环链表,并且用一个指针取记录不断插进来的新元素。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值