鏈表排序演算法
『壹』 C語言鏈表排序
#include"stdafx.h"
#include<stdlib.h>
//創建一個節點,data為value,指向NULL
Node*Create(intvalue){
Node*head=(Node*)malloc(sizeof(Node));
head->data=value;
head->next=NULL;
returnhead;
}
//銷毀鏈表
boolDestroy_List(Node*head){
Node*temp;
while(head){
temp=head->next;
free(head);
head=temp;
}
head=NULL;
returntrue;
}
//表後添加一個節點,Create(value)
boolAppend(Node*head,intvalue){
Node*n=Create(value);
Node*temp=head;
while(temp->next){
temp=temp->next;
}
temp->next=n;
return0;
}
//列印鏈表
voidPrint_List(Node*head){
Node*temp=head->next;
while(temp){
printf("%d->",temp->data);
temp=temp->next;
}
printf("\n");
}
//在鏈表的第locate個節點後(頭節點為0)插入創建的節點Create(value)
boolInsert_List(Node*head,intlocate,intvalue){
Node*temp=head;
Node*p;
Node*n=Create(value);
if(locate<0)
returnfalse;
while(locate--){
if(temp->next==NULL){
temp->next=Create(value);
returntrue;
}
temp=temp->next;
}
p=temp->next;
temp->next=n;
n->next=p;
returntrue;
}
//刪除第locate個節點後(頭節點為0)的節點
boolDelete_List(Node*head,intlocate){
Node*temp=head;
Node*p;
if(locate<0)
returnfalse;
while(locate--){
if(temp==NULL){
returnfalse;
}
temp=temp->next;
}
p=temp->next->next;
free(temp->next);
temp->next=NULL;
temp->next=p;
returntrue;
}
//獲取鏈表長度(不包括頭節點)
intSize_List(Node*head){
Node*temp=head;
intsize=0;
while(temp->next){
temp=temp->next;
size++;
}
returnsize;
}
//鏈表的三種排序(選擇,插入,冒泡)
boolSort_List(Node*head){
intt=0;
intsize=Size_List(head);
//選擇排序
/*for(Node*temp=head->next;temp!=NULL;temp=temp->next){
for(Node*p=temp;p!=NULL;p=p->next){
if(temp->data>p->data){
printf("換%d和%d\n",temp->data,p->data);
t=temp->data;
temp->data=p->data;
p->data=t;
}
}
}*/
//插入排序
/*for(Node*temp=head->next->next;temp!=NULL;temp=temp->next){
for(Node*p=head;p->next!=NULL;p=p->next){
if(p->next->data>temp->data)
{
printf("換%d和%d\n",temp->data,p->next->data);
t=temp->data;
temp->data=p->next->data;
p->next->data=t;
}
}
}*/
//冒泡排序
for(Node*temp=head->next;temp->next!=NULL;temp=temp->next){
for(Node*p=head->next;p->next!=NULL;p=p->next){
if(p->data>p->next->data){
t=p->data;
p->data=p->next->data;
p->next->data=t;
}
}
}
return0;
}
(1)鏈表排序演算法擴展閱讀:
return表示把程序流程從被調函數轉向主調函數並把表達式的值帶回主調函數,實現函數值的返回,返回時可附帶一個返回值,由return後面的參數指定。
return通常是必要的,因為函數調用的時候計算結果通常是通過返回值帶出的。如果函數執行不需要返回計算結果,也經常需要返回一個狀態碼來表示函數執行的順利與否(-1和0就是最常用的狀態碼),主調函數可以通過返回值判斷被調函數的執行情況。
『貳』 閾捐〃閫夋嫨娉閾捐〃閫夋嫨娉
閾捐〃閫夋嫨鎺掑簭錛屼竴縐嶅埄鐢ㄩ摼琛ㄧ壒鎬у疄鐜扮殑閫夋嫨鎺掑簭綆楁硶錛屽畠涓嶅悓浜庝紶緇熺殑鍦ㄦ暟緇勪腑榪涜岀殑閫夋嫨鎺掑簭銆傞摼琛ㄩ夋嫨鎺掑簭鐨勪富瑕佺壒鐐規槸閫氳繃閾捐〃鑺傜偣闂寸殑浜や簰鏉ヨ皟鏁村厓緔犵殑欏哄簭銆傚湪閾捐〃涓錛屾暟鎹瀛樺偍鍦ㄨ妭鐐逛腑錛屽洜姝や氦鎹㈣妭鐐瑰疄璐ㄤ笂灝辯瓑浜庢敼鍙樹簡鏁版嵁鐨勬帓鍒椼
姣忔℃帓搴忔搷浣滐紝閾捐〃閫夋嫨娉曚細閬嶅巻閾捐〃錛屾壘鍒版渶灝忥紙鎴栨渶澶э級鐨勮妭鐐癸紝騫跺皢鍏朵笌褰撳墠鑺傜偣榪涜屼氦鎹銆傝繖涓榪囩▼綾諱技浜庢暟緇勯夋嫨鎺掑簭錛屼絾鎿嶄綔瀵硅薄浠庣嚎鎬ф暟緇勮漿鎹涓轟簡閾捐〃緇撴瀯銆傝繖縐嶆帓搴忔柟寮忛伩鍏嶄簡鏁扮粍鐩存帴緔㈠紩鐨勯檺鍒訛紝鑰屾槸閫氳繃鑺傜偣閾炬帴瀹炵幇浜嗗厓緔犵殑縐誨姩銆
閾捐〃閫夋嫨鎺掑簭鐨勫叧閿鍦ㄤ簬鑺傜偣鎿嶄綔錛
- 棣栧厛錛岄亶鍘嗛摼琛錛屾壘鍒版渶灝忓艱妭鐐廣
- 鐒跺悗錛岄氳繃鎸囬拡璋冩暣錛屽皢鎵懼埌鐨勬渶灝忓艱妭鐐逛笌褰撳墠鑺傜偣榪炴帴銆
- 閲嶅嶆よ繃紼嬶紝鐩村埌閾捐〃瀹屽叏鎺掑簭銆
姣忎竴姝ユ搷浣滈兘鏄瀵歸摼琛ㄧ粨鏋勭殑寰璋冿紝紜淇濇暟鎹鎸夌収鍗囧簭鎴栭檷搴忔帓鍒椼傞氳繃閾捐〃閫夋嫨鎺掑簭錛屾垜浠鍙浠ョ湅鍒伴摼琛ㄥ湪鏁版嵁鎿嶄綔涓鐨勭伒媧繪у拰鐙鐗規с
『叄』 閾捐〃鐨勬彃鍏ユ帓搴忕畻娉
閾捐〃鏄涓縐嶇墿鐞嗗瓨鍌ㄥ崟鍏冧笂闈炶繛緇銆侀潪欏哄簭鐨勫瓨鍌ㄧ粨鏋勶紝鏁版嵁鍏冪礌鐨勯昏緫欏哄簭鏄閫氳繃閾捐〃涓鐨勬寚閽堥摼鎺ユ″簭瀹炵幇鐨勩傞摼琛ㄧ敱涓緋誨垪緇撶偣錛堥摼琛ㄤ腑姣忎竴涓鍏冪礌縐頒負緇撶偣錛夌粍鎴愶紝緇撶偣鍙浠ュ湪榪愯屾椂鍔ㄦ佺敓鎴愩傛瘡涓緇撶偣鍖呮嫭涓や釜閮ㄥ垎錛氫竴涓鏄瀛樺偍鏁版嵁鍏冪礌鐨勬暟鎹鍩燂紝鍙︿竴涓鏄瀛樺偍涓嬩竴涓緇撶偣鍦板潃鐨勬寚閽堝煙銆 鐩告瘮浜庣嚎鎬ц〃欏哄簭緇撴瀯錛屾搷浣滃嶆潅銆傜敱浜庝笉蹇呴』鎸夐『搴忓瓨鍌錛岄摼琛ㄥ湪鎻掑叆鐨勬椂鍊欏彲浠ヨ揪鍒癘(1)鐨勫嶆潅搴︼紝姣斿彟涓縐嶇嚎鎬ц〃欏哄簭琛ㄥ揩寰楀氾紝浣嗘槸鏌ユ壘涓涓鑺傜偣鎴栬呰塊棶鐗瑰畾緙栧彿鐨勮妭鐐瑰垯闇瑕丱(n)鐨勬椂闂達紝鑰岀嚎鎬ц〃鍜岄『搴忚〃鐩稿簲鐨勬椂闂村嶆潅搴﹀垎鍒鏄疧(logn)鍜孫(1)銆
浣跨敤閾捐〃緇撴瀯鍙浠ュ厠鏈嶆暟緇勯摼琛ㄩ渶瑕侀勫厛鐭ラ亾鏁版嵁澶у皬鐨勭己鐐癸紝閾捐〃緇撴瀯鍙浠ュ厖鍒嗗埄鐢ㄨ$畻鏈哄唴瀛樼┖闂達紝瀹炵幇鐏墊椿鐨勫唴瀛樺姩鎬佺$悊銆備絾鏄閾捐〃澶卞幓浜嗘暟緇勯殢鏈鴻誨彇鐨勪紭鐐癸紝鍚屾椂閾捐〃鐢變簬澧炲姞浜嗙粨鐐圭殑鎸囬拡鍩燂紝絀洪棿寮閿姣旇緝澶с傞摼琛ㄦ渶鏄庢樉鐨勫ソ澶勫氨鏄錛屽父瑙勬暟緇勬帓鍒楀叧鑱旈」鐩鐨勬柟寮忓彲鑳戒笉鍚屼簬榪欎簺鏁版嵁欏圭洰鍦ㄨ板繂浣撴垨紓佺洏涓婇『搴忥紝鏁版嵁鐨勫瓨鍙栧線寰瑕佸湪涓嶅悓鐨勬帓鍒楅『搴忎腑杞鎹銆傞摼琛ㄥ厑璁告彃鍏ュ拰縐婚櫎琛ㄤ笂浠繪剰浣嶇疆涓婄殑鑺傜偣錛屼絾鏄涓嶅厑璁擱殢鏈哄瓨鍙栥傞摼琛ㄦ湁寰堝氱嶄笉鍚岀殑綾誨瀷錛氬崟鍚戦摼琛錛屽弻鍚戦摼琛ㄤ互鍙婂驚鐜閾捐〃銆傞摼琛ㄥ彲浠ュ湪澶氱嶇紪紼嬭璦涓瀹炵幇銆傚儚Lisp鍜孲cheme榪欐牱鐨勮璦鐨勫唴寤烘暟鎹綾誨瀷涓灝卞寘鍚浜嗛摼琛ㄧ殑瀛樺彇鍜屾搷浣溿傜▼搴忚璦鎴栭潰鍚戝硅薄璇璦錛屽侰,C++鍜孞ava渚濋潬鏄撳彉宸ュ叿鏉ョ敓鎴愰摼琛ㄣ
『肆』 C語言,鏈表怎麼從大到小排序
//創建data型結構,為生成鏈表做准備
struct data
{
int value;
data *next;
};
//對鏈表進行排列的函數
void line(data *p,int n)
{ int temp,i,j;
data *tp;
for(i=0;i<n-1;i++)
for(j=0,tp=p;j<n-i-1;j++,tp=tp->next)
{ if(tp->value>tp->next->value)
{temp=tp->next->value;
tp->next->value=tp->value;
tp->value=temp;
}
}
}
以上是冒泡法對鏈表排序的例子;
//輸出答案的函數
void answer(data *p)
{ while(p!=NULL) {
cout<<p->value<<endl;
p=p->next;
}
}
以上是遍歷鏈表的函數p是鏈表的頭指針
『伍』 對單鏈表中元素按插入方法排序的C語言描述演算法如下,其中L為鏈表頭結點指針。請填充演算法中標出的空白處。
這個演算法有兩個循環,我們姑且稱其為外循環和內循環,誠如其他樓的一位網友所言,其內循環在第一次判斷時進不去是正常的,但後面會進去。為什麼呢?首先我們來理一下這個演算法的大體思路:這是一個針對單鏈表的排序演算法,就是說給定一個單鏈表,我們要把按照結點(這里不對頭結點進行排序,即這里討論的結點不包括頭結點)的數據域中的data值的大小從小到大進行排序,得到新的排序後的有序鏈表。我們先把鏈表的頭結點之後的部分鏈表拆下來,即p=L->next,L->next=NULL,這樣我們就拆分原來的鏈表變成了現在的兩個鏈表(我們稱只有一個頭結點的鏈表為L1,另一個全為數據項結點的鏈表為L2)。接下來我們一個一個從L2剝下單獨的結點,放到L1中,其中如果L1中已經有數據項結點,則要先進行data項比較再找到合適的地方插入。直到最後L2中的結點全部拆下來並裝到了L1上,於是排序完畢,此時的L1擁有與原來的單鏈表相同的頭結點,但是排列有序的數據項結點。
理完了整個演算法的思路後再回去看代碼就很明顯,外循環判斷「p!=NULL」的意義在於判斷L2鏈表中是否還有沒有剝完的結點,而內循環中要先判斷「q!=NULL」的第一層意義在於判斷L1鏈表是不是一個只有頭結點的空表(即無數據項結點),如果是,則直接插入,如果不是,則判斷目前L1頭結點的下一個結點q的data值是否小於等於剛從L2剝下來的結點p的data值,如果是,則說明這個p結點應該安放的位置還在q結點之後,我們還要繼續往下找,直到找到q->data > p->data的結點q或者已經到了鏈表的末尾(這也是q!=NULL的第二層意義),則停止尋找,並將p結點就放在這個位置。
說了半天忘了回答樓主的疑問,為什麼內循環永遠不會進去嗎?不是,只是第一次不會進去(當然,如果原單鏈表本身就是一個只有頭結點的鏈表時那麼後面也不會再進去了,因為空表根本不需要排序),而後面就會進去,具體原因見我上述分析即可知。
『陸』 設計兩個有序單鏈表的合並排序演算法
方法一:依次基穗取鏈表2的節點,和鏈表1中的節點比較,找好位置之後插入到鏈表1中,然後兩個鏈表指針各加一
方法二:另外亂滑建一個空鏈表,然後分別取兩個鏈表的節點搏陪卜,按照順序,放入空鏈表中
方法三:兩個鏈表先連接然後排序(效率最低的)
『柒』 單鏈表排序演算法分析
for(q=p->next;q;q=q->next) 因為每一步都要從p開始,與後面所有結構體進行比較,所以q作為這一次比較的指針,下次又從p開始,直至p為空
small=q; /*執行這句之後又回到for(q=p->next;q;q=q->next) 直到本次比較結束
temp=p->data;
p->data=small->data; 把本次找到的最小值與頭結點值進行交換,還差一句:small->data=temp;