1.队列也是一种线性的数据结构,队列的特征是先进先出,单向队列从队尾进去,队头出去。这种数据结构在程序里面的应用十分广泛。例如:在OS中,多进程的并发执行就是将就绪状态的进程(这个分类标准不唯一,我们简单的讨论一下ready的进程)排成一个队列,依次执行,一个进程下面的多线程也是如此。这一节我们采用数组(连续储存的方式)和链表(链式储存的方式)分别实现队列。
/*队列的基本实现*/ #include"stdafx.h" #include<iostream> #include<iomanip> #define MaxSize 64 using namespace std; /*基于数组的队列实现*/ typedef struct squeue{ int data[MaxSize]; int front=0;//队头指针 int rear=0;//队尾指针 }*squlink; class Squeue { private: squlink s;//s队列指针 public: Squeue(){ s = new squeue; } int push(int data);//从队尾入队 int pop();//从队头出队 int clear();//清空队列 int isFull();//队列是否已经饱和 int isEmpty();//队列是否已空 int num_of_queue();//队列中元素的个数 void print_all();//遍历输出 }; /*置空队列的算法*/ int Squeue::clear() { s->front = s->rear = 0; return 0; } /*判断队空的算法*/ int Squeue::isEmpty() { if (s->front == s->rear) { return 1;//返回1是队空 } return 0;//队非空。 } /*元素进队算法*/ int Squeue::push(int a) { if ((s->rear + 1) % MaxSize == s->front) { cout << "队满溢出" << endl; return 0; } else { /*首先使队尾指针位置加一,这样一来就有空间给入队元素*/ s->rear = (s->rear + 1) % MaxSize;//因为可能会出现假性溢出的情况,所以队Maxsize取模 s->data[s->rear] = a;//元素入队 return 1; } } /*判断是否队满的算法*/ int Squeue::isFull() { if ((s->rear + 1) % MaxSize == s->front) { return 1;//队满 } return 0;//队尚未满 } /*出队算法:返回当前队头元素*/ int Squeue::pop() { if (isEmpty()) { return 0;//队空 } else { s->front = (s->front + 1) % MaxSize; return (s->data[s->front]);//返回队头元素 } } int Squeue::num_of_queue() { int i = 0; i = (s->rear - s->front + MaxSize) % MaxSize; return i; } void Squeue::print_all() { int k = num_of_queue(); for (int i =1; i < k; i++) { cout << setw(5) << s->data[i]; } } /*链式储存的队列的实现*/ /*节点的结构*/ typedef struct link { int data; struct link*next; link(int a) { data = a; } }*linknode; typedef struct Q { linknode head;//队头指针 linknode tail;//队尾指针 int front;//队头 int rear;//队尾 }*Queue; class link_queue { private: Queue queue; public: link_queue();//默认构造函数。我需要他来做一些事情,把该队列初始化成一个状态 int push(int data);//元素进队 int pop();//元素出队 int clear();//清空队列 int isEmpty();//是否为空队列 void print_all();//遍历输出所有元素 }; link_queue::link_queue() { queue = new Q;//给Q队列分配空间 queue->front = queue->rear = 0; queue->head = new link(0);//初始化头部指针。 queue->tail = queue->head;//当前尾部指向头部 } int link_queue::push(int data) { linknode p = new link(data);//节点的开辟; if((queue->rear + 1) % MaxSize == queue->front) { cout << "队列已满" << endl; return 0; } queue->rear = (queue->rear + 1) % MaxSize;//队尾指针加一 queue->tail->next = p;//链表的头部指针指向下一个元素 queue->tail = p;//更新尾部 queue->tail->next = NULL;//尾部元素设置为空 return 0; } int link_queue::pop() { linknode p = NULL;//用来保存当前节点。 if (queue->front == queue->rear) { cout << "当前队列为空" << endl; return 0; } p = queue->head->next; queue->front = (queue->front + 1) % MaxSize;//头部元素更新 queue->head->next = p->next;//头部更新到下一个元素 int k = p->data; delete p;//删除当前节点 return k;//返回头部元素 } /*清空队列算法*/ int link_queue::clear() { linknode p = queue->head->next; linknode q = NULL; queue->front = queue->rear = 0; while (p) { q = p; p = p->next; delete q; } return 0; } int link_queue::isEmpty() { if (queue->front == queue->rear) { return 1;//空队列 } return 0;//非空队列 } void link_queue::print_all() { linknode p = queue->head->next; while (p) { cout << p->data << " "; p = p->next; } } int main() { cout << "************************" << endl; cout << "顺序储存的队列的实现" << endl; Squeue S; for (int i = 0; i < 10&& i < MaxSize; i++) { S.push(i); } S.print_all(); cout << endl; S.print_all(); cout << endl; cout << "*******************************" << endl; cout << "链式储存的队列的实现" << endl; link_queue l; for (int i = 0; i < 10; i++) { l.push(i); } l.print_all(); l.pop(); cout << endl; l.print_all(); return 0;
}
在前边两节我们讨论了线性数据结构:数组,链表,栈,队列。接下来我们需要在实际问题中应用他们。我将会在接下来的几章内容里举例讨论链表,队列与栈的应用。当然,我还会继续深入讨论数据结构:树(主要集中在二叉树,红黑树上),图论。