模板小程序链表排序(qsort/insert_sort/merge_sort)

Posted xiaoxi666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板小程序链表排序(qsort/insert_sort/merge_sort)相关的知识,希望对你有一定的参考价值。

前言

本文章整理了链表排序的三种方法,分别是快速排序、插入排序、归并排序。为适应不同用途,先给出常用的int版本,再在此基础上抽象出类模板。

目录

一、针对整数的版本(常用)

  1. 文中链表定义
  2. 链表相关操作
  3. 三种排序方法
  4. 完整测试程序

二、模板版本(适用性广泛)

  1. 文中链表定义
  2. 链表相关操作
  3. 三种排序方法
  4. 完整测试程序

总结

参考文章

一、针对整数的版本(常用)

文中链表定义:

1 //definition for singly-linked list.
2 struct ListNode
3 {
4     int val;
5     ListNode* next;
6     ListNode(int x) : val(x), next(NULL) {}
7 };

链表相关操作:

 1 //链表结点构造
 2 ListNode*  create_list_node(int val)
 3 {
 4     ListNode* pNode = new ListNode(val);
 5     return pNode;
 6 }
 7 //链表结点连接
 8 void connect_list_node(ListNode* pCur, ListNode* pNext)
 9 {
10     pCur->next = pNext;
11 }
12 
13 //销毁单个节点(其实用这个更好,不会出现空悬指针)
14 void destory_Node(ListNode** ppNode)
15 {
16     if(*ppNode != NULL)
17         delete *ppNode;
18     *ppNode = NULL;
19 }
20 
21 //链表销毁(注意,除头节点外,其他节点均变成了空悬指针,不建议此用法)
22 void destory_list(ListNode** ppHead)
23 {
24     ListNode** cur = ppHead;
25     while(*cur != NULL)
26     {
27         ListNode* tmp = (*cur)->next;//保存下一个节点
28         delete *cur;
29         *cur = NULL;
30         *cur = tmp;
31     }
32 }
33 
34 //链表打印(不支持有环的链表;如果链表有环,需判断环入口等等另外处理)
35 void print_list(ListNode* pHead)
36 {
37     ListNode* cur = pHead;
38     while(cur != NULL)
39     {
40         cout<< cur->val <<" ";
41         cur = cur->next;
42     }
43     cout<<endl;
44 }

三种排序方法:

 1 //链表快速排序
 2 class List_qsort
 3 {
 4 private:
 5     //交换元素
 6     void list_swap(int& lhs,int& rhs)
 7     {
 8         int tmp = lhs;
 9         lhs = rhs;
10         rhs = tmp;
11     }
12     //划分,使左边小于头结点元素,右边大于等于头结点元素
13     ListNode* list_partion(ListNode* pBegin,ListNode* pEnd)
14     {
15         if(pBegin == pEnd || pBegin->next == NULL)
16             return pBegin;
17 
18         ListNode* pSlow=pBegin;
19         ListNode* pFast=pBegin;
20         int key=pBegin->val;
21         while(pFast != pEnd)
22         {
23 
24             if(pFast->val < key)
25             {
26                 pSlow = pSlow->next;
27                 list_swap(pSlow->val,pFast->val);
28             }
29             pFast = pFast->next;
30         }
31 
32         list_swap(pSlow->val,pBegin->val);
33 
34         return pSlow;
35     }
36     //排序辅助函数
37     void _list_qsort(ListNode* pBegin,ListNode* pEnd)
38     {
39         if(pBegin == pEnd || NULL == pBegin->next)
40             return;
41         ListNode* mid=list_partion(pBegin,pEnd);
42         _list_qsort(pBegin,mid);
43         _list_qsort(mid->next,pEnd);
44     }
45 public:    
46     //排序入口函数(版本1:传值)
47     void list_qsort(ListNode* pHead)
48     {
49         if(pHead == NULL || pHead->next ==NULL)
50             return ;
51         _list_qsort(pHead,NULL);
52 
53     }
54 
55     /*
56     //排序入口函数(版本2:传指针)
57     void list_qsort(ListNode** ppHead)
58     {
59         if(*ppHead == NULL || (*ppHead)->next ==NULL)
60             return;
61         _list_qsort(*ppHead,NULL);
62     }
63     */
64 
65     /*
66     //排序入口函数(版本3:传引用)
67     void list_qsort(ListNode*& pHead)
68     {
69         if(NULL == pHead  || NULL == pHead->next )
70             return;
71         _list_qsort(pHead,NULL);
72     }
73     */
74 };
  1 //链表插入排序
  2 class List_insertion_sort
  3 {
  4 
  5     //版本1:指针的指针
  6 private:
  7     //对于待插入的节点,选择合适的位置插入
  8     void _list_insert_sort(ListNode** ppNode, ListNode *pNode)
  9     {
 10         ListNode* prev = NULL;
 11         ListNode* cur = NULL;
 12 
 13         if(pNode->val < (*ppNode)->val)
 14         {
 15             pNode->next = *ppNode;
 16             (*ppNode) = pNode;
 17             return;
 18         }
 19 
 20         cur = *ppNode;
 21 
 22         while(cur != NULL)
 23         {
 24             if(pNode->val < cur->val)
 25                 break;
 26 
 27             prev = cur;
 28             cur = cur->next;
 29         }
 30 
 31         pNode->next = cur;//或pNode->next = prev->next
 32         prev->next =pNode;
 33         return;
 34     }
 35 public:
 36     //首先遍历节点,一边是排序好的节点,一边是待排序的节点
 37     void list_insert_sort(ListNode** ppNode)
 38     {
 39         ListNode* prev = NULL;
 40         ListNode* cur = NULL;
 41 
 42         if(NULL == ppNode || NULL == *ppNode)
 43             return;
 44 
 45         cur = (*ppNode)->next;
 46         (*ppNode)->next = NULL;
 47 
 48         while(cur != NULL)
 49         {
 50             prev = cur;
 51             cur = cur->next;
 52             _list_insert_sort(ppNode,prev);
 53         }
 54     }
 55 
 56     /*
 57     //版本2:指针的引用
 58 private:
 59     //对于待插入的节点,选择合适的位置插入
 60     void _list_insert_sort(ListNode*& ppNode, ListNode *pNode)
 61     {
 62         ListNode* prev = NULL;
 63         ListNode* cur = NULL;
 64 
 65         if(pNode->val < ppNode->val)
 66         {
 67             pNode->next = ppNode;
 68             ppNode = pNode;
 69             return;
 70         }
 71 
 72         cur = ppNode;
 73 
 74         while(cur != NULL)
 75         {
 76             if(pNode->val < cur->val)
 77                 break;
 78 
 79             prev = cur;
 80             cur = cur->next;
 81         }
 82 
 83         pNode->next = cur;//或pNode->next = prev->next
 84         prev->next =pNode;
 85         return;
 86     }
 87 public:
 88     //首先遍历节点,一边是排序好的节点,一边是待排序的节点
 89     void list_insert_sort(ListNode*& ppNode)
 90     {
 91         ListNode* prev = NULL;
 92         ListNode* cur = NULL;
 93 
 94         if(NULL == ppNode)
 95             return;
 96 
 97         cur = ppNode->next;
 98         ppNode->next = NULL;
 99 
100         while(cur != NULL)
101         {
102             prev = cur;
103             cur = cur->next;
104             _list_insert_sort(ppNode,prev);
105         }
106     }
107 */
108 
109 };
 1 //链表归并排序
 2 class List_merge_sort
 3 {
 4 private:
 5     //合并两端链表
 6     //因为可能在头结点之前插入数据,故为ListNode** list1
 7     ListNode* list_merge(ListNode* list1, ListNode* list2)
 8     {
 9         if(NULL == list1)
10             return list2;
11         else if(NULL == list2)
12             return list1;
13 
14         ListNode* dummy = new ListNode(-1);//辅助头结点
15         dummy->next = list1;
16         ListNode* list1_cur = dummy;
17         ListNode* list2_cur = list2;
18 
19         while(list1_cur->next != NULL && list2_cur != NULL)
20         {
21             //cout<< list1_cur->next->val <<"==="<< list2_cur->val<<endl;
22             //把后面一段list2更小的元素插入前面一段list1中
23             if(list1_cur->next->val > list2_cur->val)//注意:不可以是大于等于,那样就不稳定了
24             {
25                 list2 = list2->next;
26                 list2_cur->next = list1_cur->next;
27                 list1_cur->next = list2_cur;
28                 list1_cur = list2_cur;
29                 list2_cur = list2;
30             }
31             else//后面一段list2的元素大于等于前面一段list1的元素时,前面一段指针直接后移
32                 list1_cur = list1_cur->next;
33         }
34         //后面一段list2中可能还有元素或NULL,总之把它接到list1后面
35         if(NULL == list1_cur->next)
36             list1_cur->next = list2_cur;
37         
38         ListNode* pHead = dummy->next;
39         delete dummy;//释放dummy
40         return pHead;//返回头结点
41     }
42 
43     //归并排序辅助函数(因为可能在头结点之前插入数据,故为ListNode** pHead)
44     ListNode* _list_merge_sort(ListNode** pHead)
45     {
46         if(NULL == *pHead || NULL == (*pHead)->next)
47             return *pHead;
48 
49         ListNode* pSlow = *pHead;
50         ListNode* pFast = *pHead;
51         while(pFast->next !=NULL && pFast->next->next !=NULL)
52         {
53             pSlow = pSlow->next;
54             pFast = pFast->next->next;
55         }
56 
57         ListNode* pLeftHead = *pHead;
58         ListNode* pRightHead = pSlow->next;
59         pSlow->next = NULL;//左半链表尾节点的next赋空值
60 
61         /*pLeftHead = */_list_merge_sort(&pLeftHead);
62         /*pRightHead = */_list_merge_sort(&pRightHead);
63 
64         //注意:虽然传值,但是内部状态可变,因此pLeftHead和pRightHead内部
65         //的的next可能已经变了,因此他们可能伸长或缩短
66         *pHead = list_merge(pLeftHead,pRightHead);//修改头指针
67         return *pHead;
68     }
69 public:
70     //归并排序入口,去掉了返回值,不包装这一层也行
71     void list_merge_sort(ListNode** pHead)
72     {
73         _list_merge_sort(pHead);//注意这里传入的是地址
74     }
75 };

完整测试程序:

  1 /*
  2 本程序说明:
  3 
  4 链表排序各种方法(快速排序)
  5 
  6 参考链接:
  7     http://blog.csdn.net/u012658346/article/details/51141288
  8     http://www.jb51.net/article/37300.htm
  9 
 10 */
 11 #include <iostream>
 12 using namespace std;
 13 
 14 
 15 //definition for singly-linked list.
 16 struct ListNode
 17 {
 18     int val;
 19     ListNode* next;
 20     ListNode(int x) : val(x), next(NULL) {}
 21 };
 22 
 23 //链表结点构造
 24 ListNode*  create_list_node(int val)
 25 {
 26     ListNode* pNode = new ListNode(val);
 27     return pNode;
 28 }
 29 //链表结点连接
 30 void connect_list_node(ListNode* pCur, ListNode* pNext)
 31 {
 32     pCur->next = pNext;
 33 }
 34 
 35 //销毁单个节点(其实用这个更好,不会出现空悬指针)
 36 void destory_Node(ListNode** ppNode)
 37 {
 38     if(*ppNode != NULL)
 39         delete *ppNode;
 40     *ppNode = NULL;
 41 }
 42 
 43 //链表销毁(注意,除头节点外,其他节点均变成了空悬指针)
 44 void destory_list(ListNode** ppHead)
 45 {
 46     ListNode** cur = ppHead;
 47     while(*cur != NULL)
 48     {
 49         ListNode* tmp = (*cur)->next;//保存下一个节点
 50         delete *cur;
 51         *cur = NULL;
 52         *cur = tmp;
 53     }
 54 }
 55 
 56 //链表打印
 57 void print_list(ListNode* pHead)
 58 {
 59     ListNode* cur = pHead;
 60     while(cur != NULL)
 61     {
 62         cout<< cur->val <<" ";
 63         cur = cur->next;
 64     }
 65     cout<<endl;
 66 }
 67 
 68 //链表快速排序
 69 class List_qsort
 70 {
 71 private:
 72     //交换元素
 73     void list_swap(int& lhs,int& rhs)
 74     {
 75         int tmp = lhs;
 76         lhs = rhs;
 77         rhs = tmp;
 78     }
 79     //划分,使左边小于头结点元素,右边大于等于头结点元素
 80     ListNode* list_partion(ListNode* pBegin,ListNode* pEnd)
 81     {
 82         if(pBegin == pEnd || pBegin->next == NULL)
 83             return pBegin;
 84 
 85         ListNode* pSlow=pBegin;
 86         ListNode* pFast=pBegin;
 87         int key=pBegin->val;
 88         while(pFast != pEnd)
 89         {
 90 
 91             if(pFast->val < key)
 92             {
 93                 pSlow = pSlow->next;
 94                 list_swap(pSlow->val,pFast->val);
 95             }
 96             pFast = pFast->next;
 97         }
 98 
 99         list_swap(pSlow->val,pBegin->val);
100 
101         return pSlow;
102     }
103     //排序辅助函数
104     void _list_qsort(ListNode* pBegin,ListNode* pEnd)
105     {
106         if(pBegin == pEnd || NULL == pBegin->next)
107             return;
108         ListNode* mid=list_partion(pBegin,pEnd);
109         _list_qsort(pBegin,mid);
110         _list_qsort(mid->next,pEnd);
111     }
112 public:    
113     //排序入口函数(版本1:传值)
114     void list_qsort(ListNode* pHead)
115     {
116         if(pHead == NULL || pHead->next ==NULL)
117             return ;
118         _list_qsort(pHead,NULL);
119 
120     }
121 
122     /*
123     //排序入口函数(版本2:传指针)
124     void list_qsort(ListNode** ppHead)
125     {
126         if(*ppHead == NULL || (*ppHead)->next ==NULL)
127             return;
128         _list_qsort(*ppHead,NULL);
129     }
130     */
131 
132     /*
133     //排序入口函数(版本3:传引用)
134     void list_qsort(ListNode*& pHead)
135     {
136         if(NULL == pHead  || NULL == pHead->next )
137             return;
138         _list_qsort(pHead,NULL);
139     }
140     */
141 };
142 
143 //链表插入排序
144 class List_insertion_sort
145 {
146 
147     //版本1:指针的指针
148 private:
149     //对于待插入的节点,选择合适的位置插入
150     void _list_insert_sort(ListNode** ppNode, ListNode *pNode)
151     {
152         ListNode* prev = NULL;
153         ListNode* cur = NULL;
154 
155         if(pNode->val < (*ppNode)->val)
156         {
157             pNode->next = *ppNode;
158             (*ppNode) = pNode;
159             return;
160         }
161 
162         cur = *ppNode;
163 
164         while(cur != NULL)
165         {
166             if(pNode->val < cur->val)
167                 break;
双向链表模板向量中的输入排序(C++)

代码模板实现双向链表的去重拼接合并排序

模板小程序二分法插入排序

算法之小细节(细节~链表的特殊结点~提升优化度)~反转链表删除排序链表中的重复元素

算法小专栏:选择排序

23. 合并K个升序链表(困难)-归并排序小顶堆