無環單鏈表的反轉
http://blog.csdn.net/feliciafay/article/details/6841115
超經典
方法一:新創建一個單鏈表
- 優點:此方法很簡單,利用單鏈表的頭插法即可
- 缺點:多創建了一張表耗費內存空間
-實現關鍵:遍歷原鏈表,創建新鏈表,新鏈表使用頭插法進行創建
具體代碼:
LinkList p = (LinkList)malloc(sizeof(node));
p->next = nill;
while(p1){//原鏈表的只一個節點
//創建一個新節點
LinkList q = (LinkList)malloc(sizeof(node));
q->data = p1->data;
//頭插法直接實現鏈表的反轉
q->next = p->next;
p->next = q;
p1 = p1->next;
}
方法二:循環順序反轉
- 優點:不用開辟新的空間,只需要3個指針變量就行
- 缺點:實現較復雜
- 實現關鍵:這種也是一種遍歷的反轉方式,主要是要一個用于循環的指針p,以及一個指針q,用于表示p的前一個節點,另外還需要一個指針用于存儲p的下一個節點
實現代碼
LinkList p = head->next->next;
LinkList q = head->next;
LinkList r;
while(p){
//利用中間指針變量對指針p的下一個節點的位置進行存儲
r = p->next;
p->next = q;
q = p;
p = r;
}
head = q;
image.png
方法三:同樣是循環遍歷的一種反轉方式
- 優點:優點在于這種實現的方式更加的省指針,不需要中間的指針,將頭指針作為中轉指針
- 缺點:邏輯更復雜
- 實現關鍵: 實現的關鍵在于換掉節點間的邏輯關系
實現代碼
Linklist p = head->next;
Linklist q;
while(p->next != null){
q = p->next;
p->next = q->next;
q->next = head->next;
head->next = q;
}
//當p后沒有節點時,將原來的頭節點鏈接過來
p->next = head;
head = p->next->next;
p->next->next = null;
方法四: 遞歸實現
- 優點:想法簡單
- 缺點:遞歸的通病就在于耗費內存空間,每遞歸一次操作系統都將把當前的上下文壓棧,因此遞歸的次數越多耗費的內存將越多
- 實現關鍵: 實現的關鍵在將問題進行劃分,將大問題劃分為多個子問題,但遞歸存在很多重復子問題,這也是為什么遞歸耗時的原因。遞歸的結束條件就是最后一個節點一經被反轉
LinkList revers(LinkList head,LinkList & new_head){
if(head = null){
return;
}
if(head->next = null){
new_head = head;
return head;
}
LinkList new_Tail = LinkList revers(head->next , new_head);
//完成反向操作
new_Tail ->next = head;
//斷開連接
head->next = null;
//返回當前的指針節點
return head;
}
總結
感覺這些方法真是太牛逼了,都很精妙,各種實現方式也是很牛逼。最后一種遞歸的方法也是很贊。保存著每一次調用的地址,在遞歸進行回溯的時候再使用。牛逼。