使用連結串列解決約瑟夫環的問題
阿新 • • 發佈:2019-01-30
已知n個人(以編號1,2,3…n分別表示)圍坐在一張圓桌周圍。從編號為1的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列,問最後一個出環的人的原編號。
用在單鏈表中刪除一個結點的思想來解決此題
設一個沒有頭結點指標的單鏈表。一個指標指向此單鏈表中間的一個結點(不是第一個,也不是最後一個結點),將該結點從單鏈表中刪除,要求時間複雜度O(1)。
圖示分析:
程式清單:
#include <iostream>
#include <malloc.h>
using namespace std;
typedef struct NODE
{
int data ;
struct NODE *next;
}Node, *LinkList;
void CreatByTail(LinkList L)
{
Node *p, *tail;
tail = L;
int i = 0;
while (i < 7)
{
p = (Node*)malloc(sizeof(Node));
p->data = i + 1;
tail->next = p;
tail = tail->next;
i++;
}
tail-> next = NULL;
}
void OutPut(LinkList L)
{
Node *p;
p = L;
while (p != NULL)
{
cout << p->data << " -> ";
p = p->next;
}
cout << "\b\b\b\b " << endl;
}
void Delete(LinkList L, Node *p)
{
Node *late;
late = p->next;
p-> data = late->data;
p->next = late->next;
free(late);
}
int main(void)
{
LinkList L;
L = (LinkList)malloc(sizeof(Node));
L->data = 0;
CreatByTail(L);
OutPut(L);
Node *p;
p = L->next->next->next;
Delete(L, p);
OutPut(L);
return 0;
}
解決約瑟夫環的問題:
首先建立一個沒有頭指標的環形連結串列,並從1到length對其初始化,即為每個人的原始編號;
定義一個計數器count,若其指向待刪除的前一個,則將它的下一個結點刪除。
程式清單:
#include <iostream>
#include <malloc.h>
//連結串列解決約瑟夫環的問題
using namespace std;
typedef struct NODE
{
int data;
struct NODE *next;
}Node, *Linklist;
//尾插法建立一個環形連結串列
void CreatByTail(Linklist L, int length)
{
Node *p, *tail;
tail = L;
int i = 1;
while (i < length)
{
p = (Node*)malloc(sizeof(Node));
p->data = i + 1;
tail->next = p;
tail = tail->next;
i++;
}
tail->next = L;//使尾指標指向頭結點,建立環形連結串列
}
void YueSeFu(Linklist L, int key)
{
Node *cur;
cur = L;
int count = 1;
while (cur->next != cur)//若相等,表明環中只剩最後一人,則迴圈結束
{
//若計數到出局號碼前一個的位置cur,則說明cur->next是需要被刪除的結點
if (count == key - 1)
{
//藉助late記錄cur->next的位置
Node *late;
late = cur->next;
//刪除cur->next(即late)
cur->next = late->next;
free(late);
//使count再從1開始計數,查詢下一個出局號碼
count = 1;
cur = cur->next;
}
else
{
cur = cur->next;
count++;
}
}
cout << "最後一個人原編號是: " <<cur->data << endl;
}
int main(void)
{
int length = 0;
int key = 0;
Linklist L;
L = (Linklist)malloc(sizeof(Node));
L->data = 1;
printf("請輸入人數: ");
scanf("%d", &length);
CreatByTail(L, length);
printf("請輸入出局編號: ");
scanf("%d", &key);
YueSeFu(L, key);
return 0;
}
執行截圖: