队列是一种特殊的线性表,是运算受到限制的一种线性表,只允许在表的一端进行插入,而在另一端进行删除元素的线性表。队尾(rear)是允许插入的一端。队头(front)是允许删除的一端。空队列是不含元素的空表。根据这样的操作。队列特点是先进先出~
基础操作代码示例:
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX 5 #define TRUE 1 #define OK 1 #define FALSE 0 #define OVERFLOW 0 typedef int Status; typedef int QElemType; using namespace std; typedef struct{ QElemType *base; int front; int rear; }SqQueue; Status InitQueue(SqQueue *Q) {//构建一个队列 Q->base =(QElemType*)malloc(MAX*sizeof(QElemType)); if(!Q->base) exit(OVERFLOW); Q->front=Q->rear=0; return OK; } Status DestroyQueue(SqQueue *Q) { if(Q->base) free(Q->base); Q->base=NULL; Q->front=Q->rear=0; return OK; } Status ClearQueue(SqQueue *Q) { Q->front=Q->rear=0; return OK; } Status QueueEmpty(SqQueue Q) { if(Q.front==Q.rear) return TRUE; else return FALSE; } int QueueLenth(SqQueue Q) { return (Q.rear- Q.front+MAX)%MAX; } Status GetHead(SqQueue Q,QElemType *e) {//取头顶元素 if(Q.front==Q.rear) return FALSE; *e=Q.base[Q.front]; return OK; } Status EnQueue(SqQueue *Q,QElemType e) {//插入元素 if((Q->rear+1)%MAX==Q->front)//满员 { cout<<"队满"<<endl; return FALSE; } Q->base[Q->rear]=e; Q->rear = (Q->rear+1)%MAX; return OK; } Status DeQueue(SqQueue *Q,QElemType *e) {//抛出元素 if(Q->front==Q->rear) return FALSE; *e = Q->base[Q->front]; Q->front = (Q->front+1)%MAX; return OK; }
约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。
分析:
(1)由于对于每个人只有死和活两种状态,因此可以用布朗型数组标记每个人的状态,可用true表示死,false表示活。
(2)开始时每个人都是活的,所以数组初值全部赋为false。
(3)模拟杀人过程,直到所有人都被杀死为止。
注:循环入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。可以通过取模来判断:
完整代码:
#include <iostream> using namespace std; #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; typedef int ElemType; typedef struct { ElemType *base; int front; int rear; int MAXSIZE; }SqQueue; Status InitQueue(SqQueue& Q,int n) { Q.base = new ElemType[100]; if(!Q.base) { cout << "创建队列失败!"; return ERROR; } Q.front=Q.rear=0; Q.MAXSIZE = n+1;//MAXSIZE是总人数+1,是为了留出一个空位置来放置rear return OK; } void QueueTraverse(SqQueue Q) { int i; i=Q.front; while(i!=Q.rear) { cout<<Q.base[i]<<" "; i=(i+1)%Q.MAXSIZE; } cout<<endl; } Status EnQueue(SqQueue& Q,ElemType e) { if((Q.rear+1)%Q.MAXSIZE==Q.front) { cout << "队列已满!"; return ERROR; } Q.base[Q.rear] = e; Q.rear = (Q.rear+1)%Q.MAXSIZE; return OK; } Status DeQueue(SqQueue& Q,ElemType& e) { if(Q.front==Q.rear) { cout << "队列为空!"; return ERROR; } e = Q.base[Q.front]; Q.base[Q.front] = 0;//0代表此位置没人: Q.front = (Q.front+1)%(Q.MAXSIZE-1);//因为此时的MAXSIZE比总的人数大1,前面rear+1了; return OK; } int main() { int n,m,i=1; SqQueue Q; ElemType e; cout << "请输入n个人(n<=100):"; cin >> n; if(n>100 || n<1) { cout << "输入人数错误!"; return 0; } InitQueue(Q,n); while(i<=n)//入队操作 { EnQueue(Q,i); i++; } cout << "\n此时的序列顺序为:"; QueueTraverse(Q); cout << "\n请输入第m个人出队(1<=m<=n):"; cin >> m; if(m>n || m<1) { cout << "m输入错误!"; return 0; } cout << endl; int Count = n;//用来记录剩下的人数 while(Count != 1) { i = 1;//i用来控制是第几个人报数 while(i != m)//当i的值不等于m的值时 { Q.front = (Q.front+1)%(Q.MAXSIZE-1);//因为此时的MAXSIZE比总的人数大1,所以需要减去1,前面rear+1了; if(Q.base[Q.front] != 0)//当此时不为0的话,i++用来控制第几个人,0代表此位置没人: { i++; } } DeQueue(Q,e); while(Q.base[Q.front] == 0)//当此时为0的时候,循环找到下一个不为0的位置 { Q.front = (Q.front+1)%(Q.MAXSIZE-1); } cout << "序号:" << e << "出局!\n"; Count--; } DeQueue(Q,e); cout << "最后一个是:" << e << endl; return 0; }