参考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;} };