模板小程序链表排序(qsort/insert_sort/merge_sort)
Posted xiaoxi666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板小程序链表排序(qsort/insert_sort/merge_sort)相关的知识,希望对你有一定的参考价值。
前言
本文章整理了链表排序的三种方法,分别是快速排序、插入排序、归并排序。为适应不同用途,先给出常用的int版本,再在此基础上抽象出类模板。
目录
一、针对整数的版本(常用)
- 文中链表定义
- 链表相关操作
- 三种排序方法
- 完整测试程序
二、模板版本(适用性广泛)
- 文中链表定义
- 链表相关操作
- 三种排序方法
- 完整测试程序
总结
参考文章
一、针对整数的版本(常用)
文中链表定义:
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++)