1.线性表 顺序表 和 链表
2.栈 链式和数组展现
3.队列(循环队列) 链式和数组展现
4.树 (二叉树) 链式和数组展现
2.栈
见自己的word文档
3.队列
循环队列
为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。
循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。 【参见动画演示】
②另一种方式就是数据结构常用的: 队满时:(rear+1)%n==front,n为队列长度(所用数组大小),由于rear,front均为所用空间的指针,循环只是逻辑上的循环,所以需要求余运算。如图情况,队已满,但是rear(5)+1=6!=front(0),对空间长度求余,作用就在此6%6=0=front(0)。
③另设一个计数值,累计队列中得元素个数,队满时:count ==maxSize;同理知,队空时,count == 0;
一、队列的概念
二、队列的分类
三、顺序队列
1、
顺序队列的表示
②由于队列的队头和队尾的位置是变化的,设置两个指针front和rear分别指示队头元素和队尾元素在向量空间中的位置,它们的初值在队列初始化时均应置为0。
2、 顺序队列的基本操作
①入队时:将新元素插入rear所指的位置,然后将rear加1。
②出队时:删去front所指的元素,然后将front加1并返回被删元素。
①入队时:将新元素插入rear所指的位置,然后将rear加1。
②出队时:删去front所指的元素,然后将front加1并返回被删元素。
注意:
①当头尾指针相等时,队列为空。
②在非空队列里,队头指针始终指向队头元素,尾指针始终指向队尾元素的下一位置。
3、
顺序队列中的溢出现象
① "下溢"现象
当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件。
② "真上溢"现象
当队列满时,做进栈运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免。
③ "假上溢"现象
由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。
② "真上溢"现象
③ "假上溢"现象
由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。
四、循环队列
1、 循环队列的基本操作
循环队列中进行出队、入队操作时,头尾指针仍要加1,朝前移动。只不过当头尾指针指向向量上界(QueueSize-1)时,其加1操作的结果是指向向量的下界0。这种循环意义下的加1操作可以描述为:
① 方法一:
if(i+1==QueueSize) //i表示front或rear
i=0;
else
i++;
② 方法二--利用"模运算"
i=(i+1)%QueueSize;
① 方法一:
② 方法二--利用"模运算"
2、 循环队列边界条件处理
循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。
解决这个问题的方法至少有三种:
① 另设一布尔变量以区别队列的空和满;
② 少用一个元素的空间。 约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);
③使用一个计数器记录队列中元素的总数(即队列长度)。
① 另设一布尔变量以区别队列的空和满;
② 少用一个元素的空间。 约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);
③使用一个计数器记录队列中元素的总数(即队列长度)。
3、程序
#define
DataType
int
#define
MAXSIZE
100
using namespace std;
typedef
struct
_CirQueue
{
DataType
data[MAXSIZE];
int
front; //头指针,队非空时指向队头元素
int
rear; //尾指针,队非空时指向队尾元素的下一位置
}CirQueue, *pCirQueue;
void
InitQueue(pCirQueue
pQueue);
bool
Empty(pCirQueue
pQueue);
bool InsertQueue(pCirQueue pQueue, DataType x);
DataType OutQueue(pCirQueue pQueue);
DataType
GetHead(pCirQueue
pQueue);
int
GetLength(pCirQueue
pQueue);
int _tmain(int argc, _TCHAR* argv[])
{
int
len = 0, data;
CirQueue
myQueue;
InitQueue(&myQueue);
if (!Empty(&myQueue))
{
printf("Queue is Empty");
}
InsertQueue(&myQueue, 1);
InsertQueue(&myQueue, 2);
InsertQueue(&myQueue, 3);
InsertQueue(&myQueue, 4);
len = GetLength(&myQueue);
data = GetHead(&myQueue);
while (Empty(&myQueue))
{
data = OutQueue(&myQueue);
cout<<endl<<data;
}
return 0;
}
//初始化:初始化一个新的队列
void
InitQueue(pCirQueue
pQueue)
{
memset(pQueue, 0, sizeof(CirQueue));
}
//队列非空判断:若队列不为空,则返回true;否则返回false。
bool
Empty(pCirQueue
pQueue)
{
if (pQueue->front != pQueue->rear)
{
return true;
}
else return false;
}
//入队列:在队列的尾部插入元素x,使元素x成为新的队尾。若 队列满,则返回false;否则,返回true。
bool InsertQueue(pCirQueue pQueue, DataType x)
{
if ((pQueue->rear+1)%MAXSIZE != pQueue->front)
//判断队列是否已满
{
pQueue->data[pQueue->rear] = x;
pQueue->rear = (pQueue->rear + 1)%MAXSIZE;
return true;
}
else
return
false;
}
//出队列:若队列不为空,则返回对头元素,并从对头删除该元素,对头指针指向原对头的后记元素;否则,返回元素NULL
DataType OutQueue(pCirQueue pQueue)
{
DataType
data;
if (pQueue->front == pQueue->rear)
{
return NULL;
}
else
{
data = pQueue->data[pQueue->front];
pQueue->front = (pQueue->front + 1)%MAXSIZE;
return data;
}
}
//取对头元素:若队列不空,则返回对头元素;否则,返回空元素NULL
DataType
GetHead(pCirQueue
pQueue)
{
if (pQueue->front == pQueue->rear)
{
return
NULL;
}
else
{
return
pQueue->data[pQueue->front];
}
}
//求队列长度
int
GetLength(pCirQueue
pQueue)
{
int
length = 0, number = 0;
for (number = pQueue->front; number%MAXSIZE < pQueue->rear; number = (number+1)%MAXSIZE)
{
length++;
}
return length;
}
运行结果: