一、單向循環鏈表
單向循環鏈表也稱約瑟夫鏈表。據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡爲止。然而Josephus和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因爲第一個人已經被越過),並殺掉第k個人。接着,再越過k-1個人,並殺掉第k個人。這個過程沿着圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活着。問題是,給定了和,一開始要站在什麼地方纔能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。
二、用C語言實現單向循環鏈表
1、構造存儲結構
typedef int datatype;
typedef struct josephus
{
datatype data; /* 數據域 */
struct josephus *next; /* 指針域 */
}josephus_list, *josephus_plist;
2、初始化
初始化主要工作:①申請頭結點空間;②
head->next=head
/* 初始化 */
void init_josephus_list(josephus_plist *list)
{
*list = (josephus_plist)malloc(sizeof(josephus_list));
if(NULL == *list)
{
printf("內存申請失敗\n");
perror("malloc"); /* 打印內存申請失敗原因 */
exit(1);
}
(*list)->next = *list; /* 將next設爲NULL,建立空鏈表 */
}
3、插入
void insert_josephus_list(josephus_plist head, josephus_plist new)
{
new->next = head->next;
head->next = new;
}
4、刪除
刪除結點和單向鏈表的刪除思想一樣。
void delete_josephus_list(josephus_plist pnode)
{
josephus_plist dnode;
dnode = pnode->next;
pnode->next = dnode->next;
free(dnode);
}
5、判斷鏈表是否爲空
即判斷
head
是否等於head->next
/* 判斷是否爲空 */
bool isempty(josephus_plist head)
{
if(head == head->next)
{
return true;
}
else
{
return false;
}
}
5、打印鏈表
void show_josephus_list(josephus_plist head)
{
josephus_plist p = NULL;
for(p = head; p->next != head; p = p->next)
{
printf("%d\t", p->data);
}
printf("%d\n", p->data);
}
三、練習題:實現約瑟夫環
1、創建鏈表
/* 創建單向循環鏈表 */
void create_josephus_list(josephus_plist head)
{
josephus_plist new = NULL;
josephus_plist p = head;
int len = 0;
int i = 0;
printf("輸入要插入數據的個數:");
scanf("%d", &len);
for(i = 0; i < len; i++)
{
if (0 == i)
{
scanf("%d", &(head->data));
}
else
{
new = (josephus_plist)malloc(sizeof(josephus_list));
if(NULL == new)
{
printf("內存申請失敗\n");
perror("malloc");
exit(1);
}
printf("輸入要插入的第%d個數據:", (i+1));
scanf("%d", &(new->data));
insert_josephus_list(p, new);
p = p->next;
}
show_josephus_list(head); /* 打印 */
}
}
2、實現約瑟夫
/* n是第n個要刪除的結點 */
void josephus(josephus_plist head, int n)
{
int i = 0;
josephus_plist p = head;
while(p != p->next)
{
for(i = 0; i < n-2; i++)
{
p = p->next;
}
printf("-->%d", p->next->data);
delete_josephus_list(p);
p = p->next;
}
printf("-->%d\n", p->data);
}
3、main函數
int main(void)
{
josephus_plist head = NULL; /* 定義一個頭指針 */
init_josephus_list(&head); /* 初始化 */
create_josephus_list(head); /* 創建單向鏈表 */
josephus(head, 3);
return 0;
}