循环链表应用——约瑟夫置换
生活随笔
收集整理的這篇文章主要介紹了
循环链表应用——约瑟夫置换
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
約瑟夫問題
介紹
約瑟夫問題,又稱約瑟夫置換、丟手絹問題。
一般形式
(本部分內容來自百度百科)
約瑟夫問題是個有名的問題:N個人圍成一圈,從第一個開始報數,第M個將被殺掉,最后剩下一個,其余人都將被殺掉。例如N=6,M=5,被殺掉的順序是:5,4,6,2,3。
代碼
問題描述
本文以以下問題為例
編號為1-10的10 個人圍成一圈,從第一個開始報數,第9個被淘汰出圈,剩下的組成新的圈。依次這樣下去,求最后一個人的編號
解決
注意:該段代碼與上篇文章——《 循環鏈表定義及操作 》相接
//解答約瑟夫問題 bool Joseph(LinkList* &L, int interval) {LinkList *p = L, *q;int i = 0, j = 0;int times = 0; //當前輪數int num = 0;if(!L || p->next == L){cout << "鏈表為空\n";return false;}if(interval < 1){cout << "報數淘汰口令不能小于1\n";return false;}do{i += interval;//找查第i個結點,p指向該結點的上一個結點while(p->next){if(p->next != L){//如果不是頭結點的話j++;}if(j >= i) break;p = p->next;}times++;q = p->next; //臨時保存被刪結點以備釋放空間num = q->data;cout << "當前結點:" << q->data<< " 上一個結點:" << p->data<<" 下一個結點:" << q->next->data<< endl;p->next = q->next;delete q; //釋放被刪除結點內存LinkListPrint(L);}while(L->next != L); //鏈表不為空,繼續報數cout << "最后一個出圈者的編號" << num << endl;return true; }完整代碼
代碼
#include <iostream> #include <string>using namespace std;typedef struct _LinkNode {int data;struct _LinkNode *next; }LinkList;bool InitList(LinkList* &L) {L = new LinkList;if(!L) return false;L->next = L;L->data = 0;return true; }bool ListInsert_back(LinkList* &L, LinkList *node) {LinkList *last = NULL;if(!L || !node) return false;if(L == L->next){//頭結點指針指向了自己(鏈表只有頭結點)node->next = L;L->next = node;}else{//非空的循環鏈表last = L->next;//尋找尾結點(指向頭結點的結點)while(last->next != L){last = last->next;}node->next = L;last->next = node;}return true; }void LinkListPrint(LinkList *L) {LinkList *p;if(!L || L == L->next){cout << "鏈表為空\n";return;}p = L->next;while(p != L){cout << p->data << "\t";p = p->next;}cout << endl; }//解答約瑟夫問題 bool Joseph(LinkList* &L, int interval) {LinkList *p = L, *q;int i = 0, j = 0;int times = 0; //當前輪數int num = 0;if(!L || p->next == L){cout << "鏈表為空\n";return false;}if(interval < 1){cout << "報數淘汰口令不能小于1\n";return false;}do{i += interval;//找查第i個結點,p指向該結點的上一個結點while(p->next){if(p->next != L){//如果不是頭結點的話j++;}if(j >= i) break;p = p->next;}times++;q = p->next; //臨時保存被刪結點以備釋放空間num = q->data;cout << "當前結點:" << q->data<< " 上一個結點:" << p->data<<" 下一個結點:" << q->next->data<< endl;p->next = q->next;delete q; //釋放被刪除結點內存LinkListPrint(L);}while(L->next != L); //鏈表不為空,繼續報數cout << "最后一個出圈者的編號" << num << endl;return true; }int main() {LinkList *L, *s;int i = 0;if(InitList(L)){cout << "創建一個空的循環鏈表\n";}else{exit(-1);}cout << "尾插10個元素...\n";while((++i)<=10){s = new LinkList;s->data = i;s->next = NULL;if(ListInsert_back(L, s)){cout << "success\n";}else{cout << "default\n";}}LinkListPrint(L);Joseph(L,9);return 0;}輸出結果
注:0為頭結點的數據,該結點并不計入約瑟夫環中(但最后也將其刪除銷毀鏈表釋放內存)
創建一個空的循環鏈表 尾插10個元素... success success success success success success success success success success 1 2 3 4 5 6 7 8 9 10 當前結點:9 上一個結點:8 下一個結點:10 1 2 3 4 5 6 7 8 10 當前結點:8 上一個結點:7 下一個結點:10 1 2 3 4 5 6 7 10 當前結點:10 上一個結點:7 下一個結點:0 1 2 3 4 5 6 7 當前結點:2 上一個結點:1 下一個結點:3 1 3 4 5 6 7 當前結點:5 上一個結點:4 下一個結點:6 1 3 4 6 7 當前結點:3 上一個結點:1 下一個結點:4 1 4 6 7 當前結點:4 上一個結點:1 下一個結點:6 1 6 7 當前結點:1 上一個結點:0 下一個結點:6 6 7 當前結點:6 上一個結點:0 下一個結點:7 7 當前結點:7 上一個結點:0 下一個結點:0 鏈表為空 最后一個出圈者的編號7總結
以上是生活随笔為你收集整理的循环链表应用——约瑟夫置换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法题——Cantor表
- 下一篇: 顺序表的应用——逆置问题