快速排序(快拍)
快速排序的思想是分治,平均时间复杂度O(nlogn),当然快速排序的时间复杂度并不是稳定的,最大时间复杂度是n^2。当然在用C语言实现的快速排序中,快速排序是原地排序,所有排序中空间复杂最低。
代码
基于数组的快速排序(递归)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void qSort(int *a, int low, int high){ if(low > high) return; int first = low; int last = high; int key = a[first]; while(first < last){ while(first < last && a[last] >= key) --last; if(first < last) a[first] = a[last]; while(first < last && a[first] <= key) ++first; if(first < last) a[last] = a[first]; } a[first] = key; Qsort(a, low, first-1); Qsort(a, first+1, high); }
|
这个版本可能便于理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| void swap(int *x, int *y) { int t = *x; *x = *y; *y = t; } void quick_sort_recursive(int arr[], int start, int end) { if (start >= end) return; int mid = arr[end]; int left = start, right = end - 1; while (left < right) { while (arr[left] < mid && left < right) left++; while (arr[right] >= mid && left < right) right--; swap(&arr[left], &arr[right]); } if (arr[left] >= arr[end]) swap(&arr[left], &arr[end]); else left++; if (left) quick_sort_recursive(arr, start, left - 1); quick_sort_recursive(arr, left + 1, end); } void quick_sort(int arr[], int len) { quick_sort_recursive(arr, 0, len - 1); }
|
php的快速排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| function qSort(&$envelopes, $start, $end ) { if($end <= $start) { return; } $i = $start; $j = $end; while($i < $j) { while($i < $end && $envelopes[$i] <= $envelopes[$start]) { $i++; } while($j > $start && $envelopes[$j] > $envelopes[$start]) { $j--; } if($i < $j) { $tmp = $envelopes[$i]; $envelopes[$i] = $envelopes[$j]; $envelopes[$j] = $tmp; } } if($envelopes[$i] < $envelopes[$start]) { $tmp = $envelopes[$start]; $envelopes[$start] = $envelopes[$j]; $envelopes[$i] = $tmp; } qSort($envelopes, $start, $i-1); qSort($envelopes, $i+1, $end); }
|
基于链表的快速排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| struct Node { int key; Node* next; }; void swap(int* a, int* b) { int tmp = *a ; *a = *b; *b = tmp; } Node* GetPartion(Node* pBegin, Node* pEnd) { int key = pBegin->key; Node* p = pBegin; Node* q = p->next; while(q != pEnd) { if(q->key < key) { p = p->next; swap(p->key,q->key); } q = q->next; } swap(&p->key,&pBegin->key); return p; } void QuickSort(Node* pBeign, Node* pEnd) { if(pBeign != pEnd) { Node* partion = GetPartion(pBeign,pEnd); QuickSort(pBeign,partion); QuickSort(partion->next,pEnd); } }
|
并归排序
并归排序的思想是分治的思想,时间复杂度 O(nlogn)。
- 如果一个链表(数组)只有一个元素或者为空直接返回。
- 如果链表(数组)可以分成尽可能相等两部分,将其分成尽可能相等两部分。
- 对于两个被分开的两个部分进行整个归并排序
- 把两个拍好序的链表(数组)进行合并。
与快拍的区别是:快排是先处理完再递归
而归并排序是先递归在处理
基于链表的并归排序。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| struct ListNode * merge(struct ListNode *l1,struct ListNode *l2) { if(l1 == NULL) return l2; if(l2 == NULL) return l1; if( (l1==NULL) &&(l2==NULL) ) return NULL; struct ListNode *head=NULL; if(l1->val < l2->val) { head=l1; l1=l1->next; } else { head=l2; l2=l2->next; } struct ListNode *p=head; while(l1 != NULL && l2 != NULL) { if(l1->val < l2->val) { p->next=l1; l1=l1->next; } else { p->next=l2; l2=l2->next; } p=p->next; } if(l1 != NULL) p->next=l1; if(l2 != NULL) p->next=l2; return head; } struct ListNode* sortList(struct ListNode* head) { if(head == NULL || head->next == NULL) return head; struct ListNode *slow=head; struct ListNode *fast=head; struct ListNode *pre=NULL; while(fast!= NULL && fast->next != NULL) { pre=slow; slow=slow->next; fast=fast->next->next; } pre->next=NULL; struct ListNode *l1=sortList(head); struct ListNode *l2=sortList(slow); return merge(l1,l2); }
|
基于数组的并归排序(递归)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void merge_sort_recursive(int arr[], int reg[], int start, int end) { if (start >= end) return; int len = end - start, mid = (len >> 1) + start; int start1 = start, end1 = mid; int start2 = mid + 1, end2 = end; merge_sort_recursive(arr, reg, start1, end1); merge_sort_recursive(arr, reg, start2, end2); int k = start; while (start1 <= end1 && start2 <= end2) reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++]; while (start1 <= end1) reg[k++] = arr[start1++]; while (start2 <= end2) reg[k++] = arr[start2++]; for (k = start; k <= end; k++) arr[k] = reg[k]; } void merge_sort(int arr[], const int len) { int reg[len]; merge_sort_recursive(arr, reg, 0, len - 1); }
|
基于数组的并归排序(迭代)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| int min(int x, int y) { return x < y ? x : y; } void merge_sort(int arr[], int len) { int* a = arr; int* b = (int*) malloc(len * sizeof(int)); int seg, start; for (seg = 1; seg < len; seg += seg) { for (start = 0; start < len; start += seg + seg) { int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len); int k = low; int start1 = low, end1 = mid; int start2 = mid, end2 = high; while (start1 < end1 && start2 < end2) b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++]; while (start1 < end1) b[k++] = a[start1++]; while (start2 < end2) b[k++] = a[start2++]; } int* temp = a; a = b; b = temp; } if (a != arr) { int i; for (i = 0; i < len; i++) b[i] = a[i]; b = a; } free(b); }
|
冒泡排序
时间复杂度与空间复杂度
时间复杂度O(n^2)
代码
c语言冒泡排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void bubbleSort(int *nums, int lenNums) { int i,j; int flag = 1; for(i = 0; i < lenNums; i++) { flag = 0; for(j=0; j< lenNums - i -1; j++) { if(nums[j] > nums[j+1]) { nums[j] = nums[j+1] + nums[j]; nums[j+1] = nums[j] - nums[j+1]; nums[j] = nums[j] - nums[j+1]; flag = 0; } } if(flag == 1) { break; } } }
|
插入排序
时间复杂度与空间复杂度
时间复杂度O(n^2),空间复杂度O(1)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| void insertSort(int *nums, int numsLen) { int tmp; for(int i = 1; i< numsLen; i++) { tmp = nums[i]; for(int j = i; j>0 && nums[j] < nums[j-1]; j--) { nums[j] = nums[j-1]; } nums[j] = tmp; } }
|
基数排序
基数排序是将 需要排序的所有数字统一为固定位数的数字
(如果位数不足向前补0),然后按照位数切割,分别对每一个位数进行比较。从最低位开始,依次进行一次排序。这样排完以后就会变成一个有序序列。
时间复杂度与空间复杂度
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| function radixsort($nums) { $maxNum = max($nums); $wei = 0; for($exp =1 ; intval(($maxNum/$exp ))> 0; $exp*=10 ) { $nums = countSort($nums,$exp); var_dump($nums); } } function countSort($nums,$exp) { for ($i=0; $i < 10; $i++) { $count[$i] = 0; } for($i = 0; $i< count($nums); $i++) { $key = intval(($nums[$i]/$exp)%10); $count[intval(($nums[$i]/$exp)%10)]++; } for($i = 1; $i < 10; $i++) { $count[$i] += $count[$i - 1]; } for($i = count($nums)-1; $i >= 0; $i--) { $output[$count[intval(($nums[$i]/$exp)%10) ] -1] = $nums[$i]; $count[intval((($nums[$i]/$exp)%10))]--; } for ($i=0; $i < count($nums) ; $i++) { $nums[$i] = $output[$i]; } return $nums; } $a = [1,3,4,5,12,412,534,122]; radixsort($a);
|
堆排序
以最大堆为例,最大堆就是一个特殊二叉树,父节点大于子节点。
当前算法是以层序遍历,将二叉树存入数组中。
- 堆排序每次把处于堆顶的最大值取出
- 然后对堆进行排序
- 一次循环,直至堆变为0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <?php function heapSort($nums) { $n = count($nums); for($i = intval($n/2) -1 ; $i >= 0; $i--) { heapify($nums, $n, $i); } for($i = $n-1; $i >= 0; $i--) { $tmp = $nums[0]; $nums[0] = $nums[$i] ; $nums[$i] = $tmp; heapify($nums, $i, 0); } var_dump($nums); } function heapify(&$nums, $n, $i) { $largest = $i; $l = $i * 2 +1; $r = $i * 2 +2; if($l < $n && $nums[$largest] < $nums[$l]) { $largest = $l; } if($r < $n && $nums[$largest] < $nums[$r]) { $largest = $r; } if($largest != $i) { $tmp = $nums[$i]; $nums[$i] = $nums[$largest]; $nums[$largest] = $tmp; heapify($nums, $n, $largest); } } $a = [1,3,4,5,12,412,534,122,534,0,77,88,99,78,56,35,34,1]; heapSort($a); }
|
桶排序