單鏈表原地逆置

2022-07-08 21:48:09 字數 1708 閱讀 2644

給定乙個帶頭結點的單鏈表,編寫演算法將其原地逆置。所謂「原地」是指空間複雜度為o(1)。有兩種方法,頭插法和冒泡法。這兩種方法的時間複雜度均為o(n)。

我們知道,用頭插法建立鍊錶,得到的鍊錶中元素的順序和輸入的順序相反,所以利用這一特點,可以將鍊錶逆置。

給定乙個帶頭結點的單鏈表l,如下圖所示。

首先用指標p儲存鍊錶第乙個結點,然後將頭結點從鍊錶中剝離下來,如下圖所示,此時鍊錶l只有乙個頭結點。

另設一指標r儲存p的後繼,將p指向的結點n1用尾插法插入到鍊錶l中,

此時p指向n2,儲存p的後繼n3,再將n2尾插到鍊錶l中,

以此類推,直至儲存後繼的指標r為空,退出迴圈。

void reverse_l1(linklist l)

return;

}

我把這種方法稱為「冒泡法」,是因為演算法流程和氣泡排序類似,只不過在氣泡排序中是相鄰的元素出現逆序才交換,而鍊錶逆置則要求每對結點之間都要交換順序。

冒泡法和頭插法不同,頭插法只有乙個工作指標p指向乙個操作物件——被摘下來的結點,以及儲存其後繼的指標r。而冒泡法有兩個工作指標,即一對工作指標,以及儲存其後繼的指標r,共計3個指標。考慮如下一般情況,

指標pre和p分別指向兩個結點,將其看作一對結點,它們是每次迴圈操作的物件。迴圈中,讓n2的後繼指向n1,即完成了(n1,n2)的逆置。之後三個指標進一,pre=p,p=r,r=r->next,重複上述逆置操作,鍊錶變成了下圖。

顯而易見,如果指標r!=null,則迴圈還要繼續下去,若r==null,迴圈結束,鍊錶逆置完成,而指標p指向逆置後的乙個元素。

上述步驟發生的前提是鍊錶中除了頭結點以外,至少有兩個結點,而為了將判斷是否繼續迴圈和是否進入迴圈結合起來,應將指標r初始置為指向第乙個結點的後繼,p指向第乙個結點,即p=l->next,r=p->next,指標pre無強制要求。

注意初始p指向的結點在完成逆置之後將成為最後乙個結點,所以應該在逆置之前將p的後繼置為空,否則逆置之後p的後繼會指向倒數第二個結點,而倒數第二個結點的後繼指向倒數第乙個結點,即逆置前的p,兩個結點之間形成環。

void reverse_l2(linklist l)

/* 頭結點指向逆置之後的第乙個結點. */

l->next = p;

return;

}

data-structure/linklist.c at master · tianshihao/data-structure (github.com)

單鏈表原地逆置

題目 是編寫演算法將帶一單鏈表逆置,要求空間複雜度為o 1 o 1 o 1 分析 單鏈表分為帶頭節點和不帶頭節點兩種,逆置思路有兩種,第一種是採用頭插法重新建立新的單鏈表,該方法直接遍歷鍊錶,每次將當前結點新增到新鍊錶的頭部 第二種是通過該錶 next指標,定義三個指標 pre,p,r,分別表示三個...

單鏈表原地逆置

1.有頭結點的單鏈表原地逆置 尾插法 bool reverse1 listnode l 翻轉後l為頭結點 return true 2.無頭結點的單鏈表原地逆置 外加乙個頭結點 bool reverse2 listnode l 最後l為尾結點 return true 3.翻轉鍊錶中第m個節點到第n個節...

單鏈表逆置

單鏈表逆置 include include define item num 10 typedef struct tagnode node node linklist create void linklist destroy node head void linklist print node hea...