C語言 用鏈表對學號進行排序,求解C語言中建立一個對鏈表按照學號進行排序的問題...

==========================

功能:選擇排序(由小到大)

返回:指向鏈表表頭的指針

==========================

*/

/*

選擇排序的基本思想就是反復從還未排好序的那些節點中,

選出鍵值(就是用它排序的字段,我們取學號num為鍵值)最小的節點,

依次重新組合成一個鏈表。

我認為寫鏈表這類程序,關鍵是理解:

head存儲的是第一個節點的地址,head->next存儲的是第二個節點的地址;

任意一個節點p的地址,只能通過它前一個節點的next來求得。

單向鏈表的選擇排序圖示:

---->[1]---->[3]---->[2]。

。。---->[n]---->[NULL](原鏈表)

head 1->next 3->next 2->next n->next

---->[NULL](空鏈表)

first

tail

---->[1]---->[2]---->[3]。

。。---->[n]---->[NULL](排序后鏈表)

first 1->next 2->next 3->next tail->next

圖10:有N個節點的鏈表選擇排序

1、先在原鏈表中找最小的,找到一個后就把它放到另一個空的鏈表中;

2、空鏈表中安放第一個進來的節點,產生一個有序鏈表,并且讓它在原鏈表中分離出來(此時要注意原鏈表中出來的是第一個節點還是中間其它節點);

3、繼續在原鏈表中找下一個最小的,找到后把它放入有序鏈表的尾指針的next,然后它變成其尾指針;

*/

struct student *SelectSort(struct student *head)

{

struct student *first; /*排列后有序鏈的表頭指針*/

struct student *tail; /*排列后有序鏈的表尾指針*/

struct student *p_min; /*保留鍵值更小的節點的前驅節點的指針*/

struct student *min; /*存儲最小節點*/

struct student *p; /*當前比較的節點*/

first = NULL;

while (head != NULL) /*在鏈表中找鍵值最小的節點。

*/

{

/*注意:這里for語句就是體現選擇排序思想的地方*/

for (p=head,min=head; p->next!=NULL; p=p->next) /*循環遍歷鏈表中的節點,找出此時最小的節點。*/

{

if (p->next->num num) /*找到一個比當前min小的節點。

*/

{

p_min = p; /*保存找到節點的前驅節點:顯然p->next的前驅節點是p。*/

min = p->next; /*保存鍵值更小的節點。*/

}

}

/*上面for語句結束后,就要做兩件事;一是把它放入有序鏈表中;二是根據相應的條件判斷,安排它離開原來的鏈表。

*/

/*第一件事*/

if (first == NULL) /*如果有序鏈表目前還是一個空鏈表*/

{

first = min; /*第一次找到鍵值最小的節點。*/

tail = min; /*注意:尾指針讓它指向最后的一個節點。

*/

}

else /*有序鏈表中已經有節點*/

{

tail->next = min; /*把剛找到的最小節點放到最后,即讓尾指針的next指向它。*/

tail = min; /*尾指針也要指向它。*/

}

/*第二件事*/

if (min == head) /*如果找到的最小節點就是第一個節點*/

{

head = head->next; /*顯然讓head指向原head->next,即第二個節點,就OK*/

}

else /*如果不是第一個節點*/

{

p_min->next = min->next; /*前次最小節點的next指向當前min的next,這樣就讓min離開了原鏈表。

*/

}

}

if (first != NULL) /*循環結束得到有序鏈表first*/

{

tail->next = NULL; /*單向鏈表的最后一個節點的next應該指向NULL*/

}

head = first;

return head;

}

/*

==========================

功能:直接插入排序(由小到大)

返回:指向鏈表表頭的指針

==========================

*/

/*

直接插入排序的基本思想就是假設鏈表的前面n-1個節點是已經按鍵值

(就是用它排序的字段,我們取學號num為鍵值)排好序的,對于節點n在

這個序列中找插入位置,使得n插入后新序列仍然有序。

按照這種思想,依次

對鏈表從頭到尾執行一遍,就可以使無序鏈表變為有序鏈表。

單向鏈表的直接插入排序圖示:

---->[1]---->[3]---->[2]。。。---->[n]---->[NULL](原鏈表)

head 1->next 3->next 2->next n->next

---->[1]---->[NULL](從原鏈表中取第1個節點作為只有一個節點的有序鏈表)

head

圖11

---->[3]---->[2]。

。。---->[n]---->[NULL](原鏈表剩下用于直接插入排序的節點)

first 3->next 2->next n->next

圖12

---->[1]---->[2]---->[3]。。。---->[n]---->[NULL](排序后鏈表)

head 1->next 2->next 3->next n->next

圖13:有N個節點的鏈表直接插入排序

1、先在原鏈表中以第一個節點為一個有序鏈表,其余節點為待定節點。

2、從圖12鏈表中取節點,到圖11鏈表中定位插入。

3、上面圖示雖說畫了兩條鏈表,其實只有一條鏈表。在排序中,實質只增加了一個用于指向剩下需要排序節點的頭指針first罷了。

這一點請讀者務必搞清楚,要不然就可能認為它和上面的選擇排序法一樣了。

*/

struct student *InsertSort(struct student *head)

{

struct student *first; /*為原鏈表剩下用于直接插入排序的節點頭指針*/

struct student *t; /*臨時指針變量:插入節點*/

struct student *p; /*臨時指針變量*/

struct student *q; /*臨時指針變量*/

first = head->next; /*原鏈表剩下用于直接插入排序的節點鏈表:可根據圖12來理解。

*/

head->next = NULL; /*只含有一個節點的鏈表的有序鏈表:可根據圖11來理解。*/

while (first != NULL) /*遍歷剩下無序的鏈表*/

{

/*注意:這里for語句就是體現直接插入排序思想的地方*/

for (t=first, q=head; ((q!=NULL) && (q->num num)); p=q, q=q->next); /*無序節點在有序鏈表中找插入的位置*/

/*退出for循環,就是找到了插入的位置*/

/*注意:按道理來說,這句話可以放到下面注釋了的那個位置也應該對的,但是就是不能。

原因:你若理解了上面的第3條,就知道了。*/

first = first->next; /*無序鏈表中的節點離開,以便它插入到有序鏈表中。*/

if (q == head) /*插在第一個節點之前*/

{

head = t;

}

else /*p是q的前驅*/

{

p->next = t;

}

t->next = q; /*完成插入動作*/

/*first = first->next;*/

}

return head;

}

/*

==========================

功能:冒泡排序(由小到大)

返回:指向鏈表表頭的指針

==========================

*/

/*

直接插入排序的基本思想就是對當前還未排好序的范圍內的全部節點,

自上而下對相鄰的兩個節點依次進行比較和調整,讓鍵值(就是用它排

序的字段,我們取學號num為鍵值)較大的節點往下沉,鍵值較小的往

上冒。

即:每當兩相鄰的節點比較后發現它們的排序與排序要求相反時,

就將它們互換。

單向鏈表的冒泡排序圖示:

---->[1]---->[3]---->[2]。。。---->[n]---->[NULL](原鏈表)

head 1->next 3->next 2->next n->next

---->[1]---->[2]---->[3]。

。。---->[n]---->[NULL](排序后鏈表)

head 1->next 2->next 3->next n->next

圖14:有N個節點的鏈表冒泡排序

任意兩個相鄰節點p、q位置互換圖示:

假設p1->next指向p,那么顯然p1->next->next就指向q,

p1->next->next->next就指向q的后繼節點,我們用p2保存

p1->next->next指針。

即:p2=p1->next->next,則有:

[ ]---->[p]---------->[q]---->[ ](排序前)

p1->next p1->next->next p2->next

圖15

[ ]---->[q]---------->[p]---->[ ](排序后)

圖16

1、排序后q節點指向p節點,在調整指向之前,我們要保存原p的指向節點地址,即:p2=p1->next->next;

2、順著這一步一步往下推,排序后圖16中p1->next->next要指的是p2->next,所以p1->next->next=p2->next;

3、在圖15中p2->next原是q發出來的指向,排序后圖16中q的指向要變為指向p的,而原來p1->next是指向p的,所以p2->next=p1->next;

4、在圖15中p1->next原是指向p的,排序后圖16中p1->next要指向q,原來p1->next->next(即p2)是指向q的,所以p1->next=p2;

5、至此,我們完成了相鄰兩節點的順序交換。

6、下面的程序描述改進了一點就是記錄了每次最后一次節點下沉的位置,這樣我們不必每次都從頭到尾的掃描,只需要掃描到記錄點為止。

因為后面的都已經是排好序的了。

*/

struct student *BubbleSort(struct student *head)

{

struct student *endpt; /*控制循環比較*/

struct student *p; /*臨時指針變量*/

struct student *p1;

struct student *p2;

p1 = (struct student *)malloc(LEN);

p1->next = head; /*注意理解:我們增加一個節點,放在第一個節點的前面,主要是為了便于比較。

因為第一個節點沒有前驅,我們不能交換地址。*/

head = p1; /*讓head指向p1節點,排序完成后,我們再把p1節點釋放掉*/

for (endpt=NULL; endpt!=head; endpt=p) /*結合第6點理解*/

{

for (p=p1=head; p1->next->next!=endpt; p1=p1->next)

{

if (p1->next->num > p1->next->next->num) /*如果前面的節點鍵值比后面節點的鍵值大,則交換*/

{

p2 = p1->next->next; /*結合第1點理解*/

p1->next->next = p2->next; /*結合第2點理解*/

p2->next = p1->next; /*結合第3點理解*/

p1->next = p2; /*結合第4點理解*/

p = p1->next->next; /*結合第6點理解*/

}

}

}

p1 = head; /*把p1的信息去掉*/

head = head->next; /*讓head指向排序后的第一個節點*/

free(p1); /*釋放p1*/

p1 = NULL; /*p1置為NULL,保證不產生“野指針”,即地址不確定的指針變量*/

return head;

}

/*

==========================

功能:插入有序鏈表的某個節點的后面(從小到大)

返回:指向鏈表表頭的指針

==========================

*/

/*

有序鏈表插入節點示意圖:

---->[NULL](空有序鏈表)

head

圖18:空有序鏈表(空有序鏈表好解決,直接讓head指向它就是了。

)

以下討論不為空的有序鏈表。

---->[1]---->[2]---->[3]。。。---->[n]---->[NULL](有序鏈表)

head 1->next 2->next 3->next n->next

圖18:有N個節點的有序鏈表

插入node節點的位置有兩種情況:一是第一個節點前,二是其它節點前或后。

---->[node]---->[1]---->[2]---->[3]。。。---->[n]---->[NULL]

head node->next 1->next 2->next 3->next n->next

圖19:node節點插在第一個節點前

---->[1]---->[2]---->[3]。

。。---->[node]。。。---->[n]---->[NULL]

head 1->next 2->next 3->next node->next n->next

圖20:node節點插在其它節點后

*/

struct student *SortInsert(struct student *head, struct student *node)

{

struct student *p; /*p保存當前需要檢查的節點的地址*/

struct student *t; /*臨時指針變量*/

if (head == NULL) /*處理空的有序鏈表*/

{

head = node;

node->next = NULL;

n += 1; /*插入完畢,節點總數加1*/

return head;

}

p = head; /*有序鏈表不為空*/

while (p->num num && p != NULL) /*p指向的節點的學號比插入節點的學號小,并且它不等于NULL*/

{

t = p; /*保存當前節點的前驅,以便后面判斷后處理*/

p = p->next; /*后移一個節點*/

}

if (p == head) /*剛好插入第一個節點之前*/

{

node->next = p;

head = node;

}

else /*插入其它節點之后*/

{

t->next = node; /*把node節點加進去*/

node->next = p;

}

n += 1; /*插入完畢,節點總數加1*/

return head;

}

/*

測試代碼如下:

*/

/*測試SelectSort():請編譯時去掉注釋塊*/

/*

head = SelectSort(head);

Print(head);

*/

/*測試InsertSort():請編譯時去掉注釋塊*/

/*

head = InsertSort(head);

Print(head);

*/

/*測試BubbleSort():請編譯時去掉注釋塊*/

/*

head = BubbleSort(head);

Print(head);

*/

/*測試SortInsert():上面創建鏈表,輸入節點時請注意學號num從小到大的順序。

請編譯時去掉注釋塊*/

/*

stu = (struct student *)malloc(LEN);

printf("/nPlease input insert node -- num,score: ");

scanf("%ld,%f",&stu->num,&stu->score);

head = SortInsert(head,stu);

free(stu);

stu = NULL;

Print(head);

*/

轉載: 。

全部

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395457.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395457.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395457.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

字符集(CHARACTER SET)和校對集(COLLATE)

http://blog.sina.com.cn/s/blog_9707fac301016wxm.html http://www.th7.cn/db/mysql/201412/84636.shtml 從上文中可以看出character_set_connection、character_set_client、 character_set_results三個字符集什么時候用到。從實際上可以看到,當客戶端連接服務器的…

shell 本地接口自動化

一.基于http/https的接口 一般情況下,當前大多公司在做接口自動化的時候都會使用一些工具;比如:postman/jmeter/python自研開發接口平臺。。。 以上的情況,都是在源碼與測試使用分離的情況下實踐的。也就是說:目前國內…

hitchhiker部署_《 Hitchhiker的Python機器學習指南》

hitchhiker部署by Conor Dewey由Conor Dewey 《 Hitchhiker的Python機器學習指南》 (The Hitchhiker’s Guide to Machine Learning in Python) 提供實施代碼,教學視頻等 (Featuring implementation code, instructional videos, and more) 趨勢 (The Trend) Machi…

CAD庫中列舉所有航路點

select distinct f1.airway_point_name,f1.latitude,f1.longitude,upper(f1.airway_point_type_name)type,f2.code_fir from airway_ordered_point f1, v_airway_point f2where f2.significant_point_idf1.airway_point_idorder by code_fir, type,airway_point_name轉載于:htt…

第50次二級c語言真題,2006年4月全國計算機等級考試二級C語言筆試試卷含答案

一、選擇題((1)一(10)每題2分,(11)一(50)每題1分,共60分)下列各題A)、B)、C)、D)四個選項中,只有一個選項是正確的,請將正確選項涂寫在答題卡相應位置上,答在試卷上不得分。(1)下列選項中不屬于結構化程序設計方法的是…

python hashlib模塊

摘要算法簡介 Python的hashlib提供了常見的摘要算法,如MD5,SHA1等等。 什么是摘要算法呢?摘要算法又稱哈希算法、散列算法。它通過一個函數,把任意長度的數據轉換為一個長度固定的數據串(通常用16進制的字符串表示&…

TZOJ 5101 A Game(區間DP)

描述 Consider the following two-player game played with a sequence of N positive integers (2 < N < 100) laid onto a 1 x N game board. Player 1 starts the game. The players move alternately by selecting a number from either the left or the right end o…

國家職業標準職業編碼查詢_為什么我學會編碼而不是從事金融職業

國家職業標準職業編碼查詢by Amir Ghafouri通過阿米爾加富里(Amir Ghafouri) 為什么我學會編碼而不是從事金融職業 (Why I learned to code instead of pursuing a career in finance) Last year I faced a major life and career decision: commit to pursuing a Chartered F…

go tool trace goalng調優工具

為什么80%的碼農都做不了架構師&#xff1f;>>> 你想知道你的Go程序在做什么嗎&#xff1f; go tool trace 可以向你揭示&#xff1a;Go程序運行中的所有的運行時事件。 這種工具是Go生態系統中用于診斷性能問題時&#xff08;如延遲&#xff0c;并行化和競爭異常…

程序員 文本編輯器 c語言,程序員必備的五款文本編輯器

原標題&#xff1a;程序員必備的五款文本編輯器程序員的工作離不開文本編輯器&#xff0c;有人說一個txt就能搞定&#xff0c;但txt面對如今復雜的要求&#xff0c;明顯有些捉襟見肘&#xff0c;下面推薦五款超級好用的文本編輯器及搭配軟件&#xff0c;絕對是程序員的大愛。程…

PCH文件的創建和配置

1.PCH文件的的創建 (1)CommandN (2)打開新建文件窗口:ios->other->PCH file&#xff0c;創建一個pch文件 2.PCH文件的配置 (1)在工程的TARGETS里邊Building Setting中搜索Prefix Header (2)然后在Precompile Prefix Header下邊的Prefix Header右邊雙擊&#xff0c;添加剛…

ci 數據庫異常捕獲_系統地捕獲錯誤:如何通過4個步驟構建GitLab CI測試管道

ci 數據庫異常捕獲by Joyz通過喬伊斯 系統地捕獲錯誤&#xff1a;如何通過4個步驟構建GitLab CI測試管道 (Catch bugs systematically: how to build a GitLab CI testing pipeline in 4 steps) Your first app is a hit the day it’s launched. But one week later, you rea…

(小白)函數一: 聲明函數的方法—語句定義法和表達式定義法的區別

一、函數的定義&#xff1a; 在說明什么是函數前先舉一個小例子&#xff1a; 大家都知道印刷術是我國的四大發明&#xff08;科普一下&#xff1a;中國四大發明&#xff1a;造紙術、印刷術、火藥、指南針&#xff09;之一&#xff0c;之所以有印刷術&#xff0c;是因為重復的抄…

android限制輸入字符的范圍,Android EditText 對輸入字數和內容范圍進行限制

在做定制機時&#xff0c;對光敏值進行范圍控制時&#xff0c;以及對區號輸入時遇到對輸入字數以及輸入內容的顯示。找了好多方法&#xff0c;終于找到了幾種方法其中EditText的addTextChangedListener功不可沒。例如對光敏值要在0到61之間。大于61時要在輸入框中自動變為61.代…

vue13過濾器 debounce延遲、limitBy、filterBy、orderBy

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>智能社——http://www.zhinengshe.com</title><meta name"viewport" content"widthdevice-width, initial-scale1.0, maximum…

Sass:一種CSS預處理器語言

http://sass-lang.com/ Sass是一種CSS預處理器語言&#xff0c;通過編程方式生成CSS代碼。因為可編程&#xff0c;所以操控靈活性自由度高&#xff0c;方便實現一些直接編寫CSS代碼較困難的代碼。 同時&#xff0c;因為Sass是生成CSS的語言&#xff0c;所以寫出來的Sass文件是不…

Python學習(五)列表的簡單操作

#!/usr/bin/env python#_*_coding:utf8_*_# 操作列表# for循環nbaStars [yaoming,kobe,manu,23,the klaw]for nbaStar in nbaStars: print(nbaStar)nbaStars [yaoming,kobe,manu,str(23),the klaw] # 這里有 int 對象&#xff0c;沒有title方法的for nbaStar in nbaStars:…

node seneca_使用Node.js和Seneca編寫國際象棋微服務,第3部分

node senecaFinishing up a three-part series on writing a rules engine with Seneca microservices.完成有關使用Seneca微服務編寫規則引擎的三部分系列文章。 Parts 1 & 2 of this series covered:本系列的第1部分和第2部分涉及&#xff1a; The Seneca microservice…

Android開發畫布銷毀,Android DialogFragment 在頁面銷毀下的使用方式

今天看到了一篇文章,講了DialogFragment的封裝方式(Android&#xff1a;我為何要封裝DialogFragment&#xff1f;),想到當初也為頁面銷毀后DialogFragment的回調方式頭疼了好久,看到了po主的思路,與當初自己想的不太一樣,就整理一下.如何在開發中遇到頁面銷毀的情況在android開…

視覺智能產品發布 阿里云這項世界第一的技術現在人人可用

用手機拍下朋友的相片&#xff0c;軟件會自動識別進行分類并將照片發送給朋友。這不是空想&#xff0c;利用視覺智能對手機相冊進行管理、分類和分享正逐步成為現實。在6月10日舉行的云棲大會上海峰會上&#xff0c;阿里云正式發布了“圖像識別”和“人臉識別”兩款視覺智能服務…