鏈表排序(冒泡、選擇、插入、快排、歸并、希爾、堆排序)

參考http://www.cnblogs.com/TenosDoIt/p/3666585.html

插入排序(算法中是直接交換節點,時間復雜度O(n^2),空間復雜度O(1)

 1 class Solution {
 2 public:
 3     ListNode *insertionSortList(ListNode *head) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         if(head == NULL || head->next == NULL)return head;
 7         ListNode *p = head->next, *pstart = new ListNode(0), *pend = head;
 8         pstart->next = head; //為了操作方便,添加一個頭結點
 9         while(p != NULL)
10         {
11             ListNode *tmp = pstart->next, *pre = pstart;
12             while(tmp != p && p->val >= tmp->val) //找到插入位置
13                 {tmp = tmp->next; pre = pre->next;}
14             if(tmp == p)pend = p;
15             else
16             {
17                 pend->next = p->next;
18                 p->next = tmp;
19                 pre->next = p;
20             }
21             p = pend->next;
22         }
23         head = pstart->next;
24         delete pstart;
25         return head;
26     }
27 };

?


選擇排序(算法中只是交換節點的val值,時間復雜度O(n^2),空間復雜度O(1)

 1 class Solution {
 2 public:
 3     ListNode *selectSortList(ListNode *head) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         //選擇排序
 7         if(head == NULL || head->next == NULL)return head;
 8         ListNode *pstart = new ListNode(0);
 9         pstart->next = head; //為了操作方便,添加一個頭結點
10         ListNode*sortedTail = pstart;//指向已排好序的部分的尾部
11         
12         while(sortedTail->next != NULL)
13         {
14             ListNode*minNode = sortedTail->next, *p = sortedTail->next->next;
15             //尋找未排序部分的最小節點
16             while(p != NULL)
17             {
18                 if(p->val < minNode->val)
19                     minNode = p;
20                 p = p->next;
21             }
22             swap(minNode->val, sortedTail->next->val);
23             sortedTail = sortedTail->next;
24         }
25         
26         head = pstart->next;
27         delete pstart;
28         return head;
29     }
30 };

?


快速排序1(算法只交換節點的val值,平均時間復雜度O(nlogn),不考慮遞歸棧空間的話空間復雜度是O(1))

這里的partition我們參考數組快排partition的第二種寫法(選取第一個元素作為樞紐元的版本,因為鏈表選擇最后一元素需要遍歷一遍),具體可以參考here

這里我們還需要注意的一點是數組的partition兩個參數分別代表數組的起始位置,兩邊都是閉區間,這樣在排序的主函數中:

void?quicksort(vector<int>&arr,?int?low,?int?high)

{

? if(low < high)

? {

?? int?middle = mypartition(arr, low, high);

?? quicksort(arr, low, middle-1);

?? quicksort(arr, middle+1, high);

? }

}

對左邊子數組排序時,子數組右邊界是middle-1,如果鏈表也按這種兩邊都是閉區間的話,找到分割后樞紐元middle,找到middle-1還得再次遍歷數組,因此鏈表的partition采用前閉后開的區間(這樣排序主函數也需要前閉后開區間),這樣就可以避免上述問題

?

 1 class Solution {
 2 public:
 3     ListNode *quickSortList(ListNode *head) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         //鏈表快速排序
 7         if(head == NULL || head->next == NULL)return head;
 8         qsortList(head, NULL);
 9         return head;
10     }
11     void qsortList(ListNode*head, ListNode*tail)
12     {
13         //鏈表范圍是[low, high)
14         if(head != tail && head->next != tail)
15         {
16             ListNode* mid = partitionList(head, tail);
17             qsortList(head, mid);
18             qsortList(mid->next, tail);
19         }
20     }
21     ListNode* partitionList(ListNode*low, ListNode*high)
22     {
23         //鏈表范圍是[low, high)
24         int key = low->val;
25         ListNode* loc = low;
26         for(ListNode*i = low->next; i != high; i = i->next)
27             if(i->val < key)
28             {
29                 loc = loc->next;
30                 swap(i->val, loc->val);
31             }
32         swap(loc->val, low->val);
33         return loc;
34     }
35 };

?

快速排序2(算法交換鏈表節點,平均時間復雜度O(nlogn),不考慮遞歸棧空間的話空間復雜度是O(1))

這里的partition,我們選取第一個節點作為樞紐元,然后把小于樞紐的節點放到一個鏈中,把不小于樞紐的及節點放到另一個鏈中,最后把兩條鏈以及樞紐連接成一條鏈。

這里我們需要注意的是,1.在對一條子鏈進行partition時,由于節點的順序都打亂了,所以得保正重新組合成一條新鏈表時,要和該子鏈表的前后部分連接起來,因此我們的partition傳入三個參數,除了子鏈表的范圍(也是前閉后開區間),還要傳入子鏈表頭結點的前驅;2.partition后鏈表的頭結點可能已經改變

class Solution {
public:ListNode *quickSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//鏈表快速排序if(head == NULL || head->next == NULL)return head;ListNode tmpHead(0); tmpHead.next = head;qsortList(&tmpHead, head, NULL);return tmpHead.next;}void qsortList(ListNode *headPre, ListNode*head, ListNode*tail){//鏈表范圍是[low, high)if(head != tail && head->next != tail){ListNode* mid = partitionList(headPre, head, tail);//注意這里head可能不再指向鏈表頭了qsortList(headPre, headPre->next, mid);qsortList(mid, mid->next, tail);}}ListNode* partitionList(ListNode* lowPre, ListNode* low, ListNode* high){//鏈表范圍是[low, high)int key = low->val;ListNode node1(0), node2(0);//比key小的鏈的頭結點,比key大的鏈的頭結點ListNode* little = &node1, *big = &node2;for(ListNode*i = low->next; i != high; i = i->next)if(i->val < key){little->next = i;little = i;}else{big->next = i;big = i;}big->next = high;//保證子鏈表[low,high)和后面的部分連接little->next = low;low->next = node2.next;lowPre->next = node1.next;//為了保證子鏈表[low,high)和前面的部分連接return low;}
};

?

?


歸并排序(算法交換鏈表節點,時間復雜度O(nlogn),不考慮遞歸棧空間的話空間復雜度是O(1))????????????????????????本文地址

首先用快慢指針的方法找到鏈表中間節點,然后遞歸的對兩個子鏈表排序,把兩個排好序的子鏈表合并成一條有序的鏈表。歸并排序應該算是鏈表排序最佳的選擇了,保證了最好和最壞時間復雜度都是nlogn,而且它在數組排序中廣受詬病的空間復雜度在鏈表排序中也從O(n)降到了O(1)

class Solution {
public:ListNode *mergeSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//鏈表歸并排序if(head == NULL || head->next == NULL)return head;else{//快慢指針找到中間節點ListNode *fast = head,*slow = head;while(fast->next != NULL && fast->next->next != NULL){fast = fast->next->next;slow = slow->next;}fast = slow;slow = slow->next;fast->next = NULL;fast = sortList(head);//前半段排序slow = sortList(slow);//后半段排序return merge(fast,slow);}}// merge two sorted list to oneListNode *merge(ListNode *head1, ListNode *head2){if(head1 == NULL)return head2;if(head2 == NULL)return head1;ListNode *res , *p ;if(head1->val < head2->val){res = head1; head1 = head1->next;}else{res = head2; head2 = head2->next;}p = res;while(head1 != NULL && head2 != NULL){if(head1->val < head2->val){p->next = head1;head1 = head1->next;}else{p->next = head2;head2 = head2->next;}p = p->next;}if(head1 != NULL)p->next = head1;else if(head2 != NULL)p->next = head2;return res;}
};

?

?


冒泡排序(算法交換鏈表節點val值,時間復雜度O(n^2),空間復雜度O(1))

class Solution {
public:ListNode *bubbleSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//鏈表快速排序if(head == NULL || head->next == NULL)return head;ListNode *p = NULL;bool isChange = true;while(p != head->next && isChange){ListNode *q = head;isChange = false;//標志當前這一輪中又沒有發生元素交換,如果沒有則表示數組已經有序for(; q->next && q->next != p; q = q->next){if(q->val > q->next->val){swap(q->val, q->next->val);isChange = true;}}p = q;}return head;}
};

?



轉載于:https://www.cnblogs.com/StarZhai/p/9984230.html

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

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

相關文章

zookeeper使用和原理探究

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 zookeeper介紹 zookeeper是一個為分布式應用提供一致性服務的軟件&#xff0c;它是開源的Hadoop項目中的一個子項目&#xff0c;并且根據…

thinkphp如何部署到寶塔面板nginx服務器

原理&#xff1a;一般本地都會使用apache服務器&#xff0c;這個對pathinfo&#xff08;兩個&#xff0c;一個是環境變量$_SERVER[PATH_INFO]&#xff0c;另一個是pathinfo函數&#xff09;路由解析非常支持的&#xff0c;不需要部署什么&#xff0c; 但是nginx是對pathinfo函…

Android獲取所有應用的資源id和對應的uri

背景在某些應用中&#xff0c;為了實現應用apk資源放入重復利用&#xff0c;或者使用反射得到本應用的資源&#xff0c;需要使用反射方式獲得&#xff0c;但Resources類中也自帶了這種獲取方式&#xff0c;并且功能更加強大你可以獲取string,color,drawable,raw,xml等文件&…

nginx的腳本引擎(一)

nginx的腳本的語法和shell是很像的&#xff0c;我大致看了一下覺得挺有意思的&#xff0c;就想寫寫記錄一下。我沒看過shell腳本的引擎&#xff0c;不知道nginx腳本引擎和shell腳本引擎像不像&#xff0c;但是我覺得nginx的腳本引擎有點像C和匯編。 ngx_http_script_engine_t這…

一個待辦事列表todolist

最近有位老師讓我做的&#xff0c;圖片在下面&#xff0c;做了4個多小時&#xff0c;ui有的簡陋&#xff0c;可以再美化一下&#xff0c;這個會更好看&#xff0c;畢竟我也不是專業前端&#xff0c;測試網站http://todolist.sshouxin.top/使用的是thinkphp5.1的框架&#xff0c…

詳細說明 SourceTree 免登錄,跳過初始設置的方法(Windows 版 )

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 首先&#xff0c;安裝完 SourceTree 以后先運行一次&#xff0c;彈出初始化登錄頁面后退出。 2. 進入這個文件夾&#xff1a;C:\Users…

什么是好的API設計?

摘要&#xff1a;有人言&#xff0c;API設計是編程工作中最難的事情。甚至有人認為至少要有10年的工作經驗才能接觸它。不過這里提出了一個引人思考的問題&#xff1a;究竟是構建什么樣的庫需要花費10年的時間去學習&#xff1f; 有人言&#xff0c;API設計是編程工作中最難的事…

Linux學習記錄-文件、目錄與磁盤

用戶和群組 用戶和群組主要是為了區分用戶對文件的操作權限。 賬號在/etc/passwd個人密碼在/etc/shadow組信息在/etc/group 不要亂動這3個文件文件權限和目錄配置 文件屬性 文件前綴解釋&#xff0c;例如&#xff1a; 第一個字符代表這個文件是『目錄、文件或鏈接文件等等』&am…

php curl模擬https請求

https請求(支持GET和POST) function http_request($url,$data null){$curl curl_init();curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);if(!empty($data)){curl_setopt($cur…

springboot集成環信sdk報錯

import io.swagger.client.ApiException; import io.swagger.client.api.MessagesApi; import io.swagger.client.model.Msg 這個是因為少兩個包&#xff0c;只需要把在你的pom.xml添加以下代碼即可&#xff0c;不要忘記點贊哈只需要添加兩個包即可&#xff0c;你可以自行網上下…

解決 error: Your local changes to the following files would be overwritten by merge:XXXX

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 idea 上將本地代碼推送到 git后 , 報錯如下圖 error: Your local changes to the following files would be overwritten by merge:src/…

深度有趣 | 30 快速圖像風格遷移

簡介 使用TensorFlow實現快速圖像風格遷移&#xff08;Fast Neural Style Transfer&#xff09; 原理 在之前介紹的圖像風格遷移中&#xff0c;我們根據內容圖片和風格圖片優化輸入圖片&#xff0c;使得內容損失函數和風格損失函數盡可能小 和DeepDream一樣&#xff0c;屬于網絡…

轉型從思維習慣的轉變開始

摘要&#xff1a;首先建議大家不要輕易轉向管理崗位&#xff0c;要認清自己是否適合做管理。轉型過程中應把握好幾點&#xff1a;良好的技術基礎&#xff0c;它是贏得團隊信任的前提&#xff0c;是把握團隊整體方向的關鍵&#xff1b;培養大局觀&#xff0c;只有站得高才能看得…

數據庫小知識點(一直更新)

一、mysql查詢是否含有某字段&#xff1a; mysql數據庫查詢帶有某個字段的所有表名 SELECT * FROM information_schema.columns WHERE column_namecolumn_name; oracle數據庫查詢帶有某個字段的所有表名 select column_name,table_name,from user_tab_columns where column_n…

其他運算符

原文地址&#xff1a;https://wangdoc.com/javascript/ void運算符 void運算符的作用是執行一個表達式&#xff0c;然后不返回任何值&#xff0c;或者說返回undefined。 void 0 // undefined void(0) // undefined 上面是void運算符的兩種寫法&#xff0c;都正確。建議采用后一…

git pull --rebase 做了什么? 以及 Cannot rebase: You have unstaged changes 解決辦法

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 最近剛學 git rebase&#xff0c;覺得很牛逼的樣子&#xff0c; 結果今天就被打臉了。 git pull --rebase 1 報錯&#xff1a; Cann…

vue如何實現單頁緩存方案分析

實現全站的頁面緩存&#xff0c;前進刷新&#xff0c;返回走緩存&#xff0c;并且能記住上一頁的滾動位置&#xff0c;參考了很多技術實現&#xff0c;github上的導航組件實現的原理要么使用的keep-alive&#xff0c;要么參考了keep-alive的源碼&#xff0c;但是只用keep-alive…

C語言常用函數簡介

一、字符測試函數 isupper()測試字符是否為大寫英文字ispunct()測試字符是否為標點符號或特殊符號isspace()測試字符是否為空格字符isprint()測試字符是否為可打印字符islower()測試字符是否為小寫字母isgraphis()測試字符是否為可打印字符isdigit()測試字符是否為阿拉伯數字i…

thinkphp如何增加session的過期時間

原理&#xff1a;我們都知道session是建立在cookie的基礎上的&#xff0c;如果瀏覽器cookie清楚了&#xff0c;則tp就會重新建立一個session。 操作&#xff1a;直接增加瀏覽器的cookie的到期時間&#xff0c;就可以使tp的session增加。

需求心得

電路圖是人們為研究、工程規劃的需要。我們組項目需要設計實現一個矢量圖編輯器。在通過對變電站的電路圖進行矢量繪圖后&#xff0c;就可以通過矢量圖的縮放詳細信息。在分析需求后&#xff0c;寫下心得&#xff01; 分析需求主要有一下幾個步驟&#xff1a; 1. 獲取和引導需求…