佇列基礎及其約瑟夫問題應用
阿新 • • 發佈:2018-11-05
佇列是一種特殊的線性表,是運算受到限制的一種線性表,只允許在表的一端進行插入,而在另一端進行刪除元素的線性表。隊尾(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約瑟夫問題是個有名的問題:N個人圍成一圈,從第一個開始報數,第M個將被殺掉,最後剩下一個,其餘人都將被殺掉。例如N=6,M=5,被殺掉的順序是:5,4,6,2,3,1。 分析: (1)由於對於每個人只有死和活兩種狀態,因此可以用布朗型陣列標記每個人的狀態,可用true表示死,false表示活。 (2)開始時每個人都是活的,所以陣列初值全部賦為false。 (3)模擬殺人過程,直到所有人都被殺死為止。 注:迴圈入隊時尾指標向前追趕頭指標;出隊時頭指標向前追趕尾指標,造成隊空和隊滿時頭尾指標均相等。因此,無法通過條件front==rear來判別佇列是"空"還是"滿"。可以通過取模來判斷: 完整程式碼: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; }
#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; }