您的位置:首页 > 理论基础 > 数据结构算法

数据结构_线性表_顺序队列_循环队列_链队列

2016-05-09 10:19 531 查看
个位看官,由于队列操作相对简单,我啥也不多说,直接上代码,欢迎验证!!!

#pragma mark --abstract
//队列(queue)是只允许在表的一端进行插入,在表的另一端进行删除的线性表,允许插入的一端称为队尾(rear)
//允许删除的一端叫做队头(font),不含元素的队列称为空队列
//队列的特点是先进先出(FIFO线性表)

#pragma mark --分类
//1.队列的顺序存储结构称为顺序队列(sequential queue),他是由存放队列的一维数组和分别指向队头和队尾的指针组成.通常约定:队尾指针指示的队尾元素在一维数组中的当前位置,队头指针指向队头元素在一维数组中的当前位置的前一个位置

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#pragma mark --顺序队列的定义

#if 0
#define maxsize 10 //队列可能的最大长度
typedef int elemtype;
typedef struct {

elemtype elem[maxsize];
int font,rear;

}sequeuetp;
#endif
//假设sa为sequeuetp 的一个变量
//入队操作
//sq.rear=sq.rear+1;
//sq.elem[sq.rear]=x;

//出队操作
//sq.font=sq.font+1

//空队列sq.font=sq.rear

//满栈的sq.rear=maxsize ,这就有假溢出现象,就出现了
//2.循环队列
//循环的表,设想把sq.elem[0]接在sq.elem[maxsize-1]之后,利用取模运算就很容易实现循环意义的加1操作
//入队
//sq.rear=(sq.rear+1)%maxsize
//sq.elem[sq.rear]=x;

//出队
//sq.font=(sq.font+1)%maxsize

//对空sq.rear=sq.font;
//队满 (sq.rear+1)%maxsize=sq.font;

#pragma mark -------------循环队列的定义--------------------
#define maxsize 11 //(循环队列的最大长度10 +1)
typedef int elemtype;

typedef struct {

elemtype elem[maxsize];
int font,rear;

}cqueuetp;

#pragma mark --队列的初始化操作
void initQueue(cqueuetp*cq) {

cq->font=0;
cq->rear=0;

}

#pragma mark 判断队列是否为空
bool QueueEmpty(cqueuetp*cq) {

return (*cq).font==(*cq).rear?true:false;
}

#pragma mark 求队列的长度
int size(cqueuetp*cq) {
// 加上maxsize 时考虑到cq->rear -cq->font<0的情况
return (maxsize+cq->rear-cq->font)%maxsize;
}

#pragma mark 读取队头的元素

elemtype Head(cqueuetp*cq) {

if (cq->rear==cq->font) {//循环队列不为空
return NULL;
}
else {

return cq->elem[cq->font+1]%maxsize;
}

}

#pragma mark 入队操作
void EntrayQueue(cqueuetp*cq,elemtype x) {

if ((cq->rear+1)%maxsize==cq->font) { //队满
printf("overflow\n");
}
else {

cq->rear=(cq->rear+1)%maxsize;
cq->elem[cq->rear]=x;
}

}

#pragma mark 出队操作

elemtype DeletQueue(cqueuetp*cq) {

if ((*cq).font==(*cq).rear) {
return NULL;
}else {

cq->font=(cq->font+1)%maxsize;
return (cq->elem[cq->font]);
}

}

#pragma mark  ------------------链队列---------------------
//和栈的顺序存储一样,队列的顺序存储也可能存在溢出的现象,因此考虑队列的链式存储结构
//队列的链式存储结构成为链队列(linked queue),它实际上是一个同时带有头指针和尾指针的单链表,
//头指针指向头结点,尾指针指向尾结点,虽然用头指针就可以唯一确定这个单链表,但是插入操作总是在
//队尾进行,如果没有队尾指针,入队的时间复杂程度,将有O(1)升至O(n)

//判空的条件 lq.front=lq.rear;

#pragma mark --链队列的定义
typedef struct node{

elemtype data;
struct node*next;;

}nodetype;
typedef struct {
nodetype *front;
nodetype *rear;

}lqueue;

#pragma mark --初始化
void initLqueue(lqueue*lq) {
//设置一个空队列
lq->front=(nodetype*)malloc(sizeof(nodetype));
lq->front->next=NULL;
lq->rear=lq->front;

}

#pragma  mark --判空
bool EmptyLqueue(lqueue*lq) {

return lq->front==lq->rear?true:false;
}

#pragma mark --求队长
int lqSize(lqueue*lq) {

int i=0;
nodetype*p=lq->front->next;
while (p) {
i++;
p=p->next;
}
return i;
}

#pragma mark --读取队头元素操作

elemtype getHead(lqueue*lq) {

if (lq->front==lq->rear) {
return NULL;
}
else {

return lq->front->next->data;
}

}

#pragma mark 入队操作
void EntryQueue(lqueue*lq,elemtype x){
nodetype*s;
s=(nodetype*)malloc(sizeof(nodetype));
s->data=x;
s->next=NULL;
lq->rear->next=s;
lq->rear=s;

}

#pragma mark 出队操作

elemtype delQueue(lqueue*lq){

elemtype x;
nodetype*p;
if (lq->front==lq->rear) {
return NULL;
}
else {

p=lq->front->next;
lq->front->next=p->next;
if (p->next==NULL) //当链队列中仅有一个结点时,出队时要修改队尾指针
lq->rear=lq->front;

x=p->data;
free(p);
return x;

}

}

#pragma mark 总结
//1>链队列和链栈类似,无需判断栈满的情况
//2>在出队列的时候,原队列只有一个结点时,该结点既是队头也是队尾,姑删除此结点时必须修改队尾指针,且删除此结点后队列变成空
//3>和链栈情况相同,对于链队列,一般不会产生队满,由于队列的长度一般比较大,所以用链式存储结构比顺序存储结构更有利
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: