前面介紹了單鏈表的一些練習題,本節介紹迴圈鍊錶,顧名思義,肯定得迴圈起來,就是表中的最後乙個結點的指標指向頭結點,使整個鍊錶形成乙個環。
根據前面單鏈表中介紹的頭插法和尾插法,稍微思考一下,就知道再迴圈鍊錶中應該選擇用尾插法這種方式來建立迴圈鍊錶,因為尾插法每次都是在鍊錶的末尾插入新的元素。
和原來的尾插法建立單鏈表只是多了一行**,就是tail->next=head,也就是讓鍊錶迴圈起來。
struct linklist *tailinsert()
else
}tail->next=head;
return head;
}
遍歷迴圈鍊錶和求迴圈鍊錶的長度也都和原來一樣,只不過現在的迴圈判斷條件是tmp!=head,**如下:
int length(struct linklist *head)
return i;
}void display(struct linklist *head)
printf("\n");
}
運用迴圈鍊錶來解決約瑟夫環問題,真是再恰當不過了,問題描述如下: 有n只猴子,按順時針方向圍成一圈選大王(編號從1到n),從第1號開始報數,一直數到m,數到m的猴子退出圈外,剩下的猴子再接著從1開始報數。就這樣,直到圈內只剩下乙隻猴子時,這個猴子就是猴王,程式設計求輸入n,m後,輸出最後猴王的編號
在實際運用中,唯一的不同就是由於有頭結點的存在,判斷會很繁瑣,所以直接建立的時候,就讓tail->next=head->next,雖然還是返回頭結點head,另外在刪除的時候我原來寫的是只有乙個節點p,直接p->next=p->next->next,但是如果當m=1,也就是說現在如果是1 2 3 4 5 6,那麼挨個出去的順序就是1 2 3 4 5 6,用乙個指標沒法解決這個問題,還是需要乙個「前驅指標」q始終指向p的前乙個結點。
struct linklist *insertlinklist(int n)
else
}tail->next=head->next;
return head;
}void joseph()
q->next=p->next;
free(p);
p=q;
n--;
}printf("%d\n",q->next->data);
}}
補充:最近看書發現,我寫的約瑟夫環**過於冗餘,還是書上的簡潔,可能是我的用了頭結點的緣故。
經典簡潔的**,收藏
int jesoph(int m,int n)
while(x!=x->next)
printf("最後乙個留下來的序號:%d\n",x->data);
return x->data;
}
最後,總的**如下:
#include #include struct linklist;
struct linklist *tailinsert()
else
}tail->next=head;
return head;
}int length(struct linklist *head)
return i;
}void display(struct linklist *head)
printf("\n");
}struct linklist *insertlinklist(int n)
else
}tail->next=head->next;
return head;
}void joseph()
q->next=p->next;
free(p);
p=q;
n--;
}printf("%d\n",q->next->data);
}}int main(int argc, char *argv)
鍊錶演算法五之雙向鍊錶
如果文章有什麼錯誤或者有什麼建議,歡迎提出,大家共同交流,一起進步
鍊錶之迴圈鍊錶
單向鍊錶 鍊錶之單向鍊錶 迴圈鍊錶是單向鍊錶的變化形式。單向鍊錶的尾部的指標域是空的,而迴圈鍊錶的尾部指標是指向鍊錶的頭結點的,其結構如圖一所示。圖 一循 環鏈表結 構圖一 迴圈鍊錶結構 圖一迴圈鍊錶 結構從上面結構可以看出,迴圈鍊錶的節點形成了乙個圈。在進行遍歷時,可以從任意節點開始。如果記錄了尾...
四 迴圈鍊錶和雙向鍊錶
迴圈鍊錶 迴圈鍊錶是鏈式儲存結構的另一種形式,特點是單鏈表的最後乙個結點 終端結點 的指標域不為空,而是指向鍊錶的頭結點,使整個鍊錶形成乙個環。例子 將值為x的新結點插入到從大到小有序迴圈鍊錶的適當位置 int insertdata linklist head,int x p next s 插入s結...
(四)迴圈鍊錶及雙向鍊錶
約瑟夫問題 迴圈鍊錶的特點 判斷單鏈表中是否有環 例題雙向鍊錶 對於單鏈表,由於每個結點只儲存了向後的指標,到了尾部標識就停止了向後鏈的操作。也就是說,按照這樣的方式,只能索引後繼節點,不能索引前驅節點。不從頭結點出發就無法訪問到全部節點,故有了迴圈鍊錶 鍊錶儲存結構定義 typedef struc...