排序算法
输入:整数数组nums
输出: 按照升序排序
1 2 3 4 5 vector<int > sortArray (vector<int >& nums) { return nums; }
选择排序 思想:每次选择数组当前数组中最小的元素,放置到数组当前未选定的最前的位置
时间复杂度:n^2
1 2 3 4 5 6 7 8 9 10 11 12 vector<int > sortArray (vector<int >& nums) { int n = nums.size (); for (int i = 0 ; i < n-1 ; ++i){ for (int j = i+1 ; j < n; ++j){ if (nums[i] > nums[j]){ std::swap (nums[i], nums[j]); } } } return nums; }
冒泡排序 思想:
每次比较相邻的元素,如果前面的元素大于后面的元素,则进行交换
当某一轮没有进行交换时,说明数组已经有序
时间复杂度:n^2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 vector<int > sortArray (vector<int >& nums) { int n = nums.size (); for (int i = 0 ; i < n; ++i){ bool flag = 0 ; for (int j = 0 ; j < n-i-1 ; ++j){ if (nums[j] > nums[j+1 ]){ std::swap (nums[j], nums[j+1 ]); flag = 1 ; } } if (flag == 0 )return nums; } return nums; }
插入排序 思想:
从前往后选择元素,插入到前面已经排序好的数组元素当中
始终保证当前元素前半部分都是有序的,直到所有元素遍历完
时间复杂度:n^2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 vector<int > sortArray (vector<int >& nums) { int n = nums.size (); for (int i = 1 ; i < n; ++i){ for (int j = i-1 ; j >= 0 ; --j){ if (nums[j+1 ] >= nums[j]){ break ; } else { std::swap (nums[j+1 ], nums[j]); } } } return nums; }
归并排序 思想:分治法
将长度为n的数组分为两个长度为n/2的数组
继续分为长度为n/4的数组,最后分为长度为1的数组
分别对长度为1的两两数组进行合并
对长度为2的两两数组进行合并
长度为4的两两数组进行合并
最后对长度为n/2的数组进行合并得到的就是长度为n的有序数组
因为合并过程中依赖的小序列都是有序的,通过选择最小元素很容易合并
时间复杂度:nlog(n)
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 void merge (vector<int >& nums, int left, int mid, int right) { int n1 = mid - left + 1 ; int n2 = right - mid; vector<int > L (n1) , R (n2) ; for (int i = 0 ; i < n1; i++) L[i] = nums[left + i]; for (int j = 0 ; j < n2; j++) R[j] = nums[mid + 1 + j]; int i = 0 , j = 0 , k = left; while (i < n1 && j < n2) { if (L[i] <= R[j]) { nums[k] = L[i]; i++; } else { nums[k] = R[j]; j++; } k++; } while (i < n1) { nums[k] = L[i]; i++; k++; } while (j < n2) { nums[k] = R[j]; j++; k++; } }void mergeSort (vector<int >& nums, int left, int right) { if (left < right) { int mid = left + (right - left) / 2 ; mergeSort (nums, left, mid); mergeSort (nums, mid + 1 , right); merge (nums, left, mid, right); } }vector<int > sortArray (vector<int >& nums) { mergeSort (nums, 0 , nums.size () - 1 ); return nums; }
快速排序 思想:分治法,快排要注意要从right开始
选择一个主元
将小于主元的元素放在左边
将大于主元的元素放在右边
主元的位置则可以确定
分别对主元左边的数组和右边的数组再次进行快速排序
时间复杂度:nlog(n)
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 int partion (vector<int >& nums, int left, int right) { int value = nums[left]; int idx = left; while (left < right){ while (left < right && nums[right] >= value)right--; nums[idx] = nums[right]; idx = right; while (left < right && nums[left] <= value)left++; nums[idx] = nums[left]; idx = left; } nums[idx] = value; return left; } void quicksort (vector<int >& nums, int left, int right) { if (left >= right)return ; int mid = partion (nums, left, right); quicksort (nums, left, mid - 1 ); quicksort (nums, mid+1 , right); }vector<int > sortArray (vector<int >& nums) { quicksort (nums, 0 , nums.size () - 1 ); return nums; }
堆排序 思想:
将数组看成一棵完全二叉树,按照数组中的元素建立大顶堆
交换堆顶元素和当前最末端元素,此时最大的元素到了数组尾部,锁定位置
对当前堆进行更新
时间复杂度:nlg(n)
建堆时间为lg(n)
取出元素为1,更新堆为lg(n)
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 void heapify (vector<int >& nums, int n, int i) { int largest = i; int left = 2 * i + 1 ; int right = 2 * i + 2 ; if (left < n && nums[left] > nums[largest]) largest = left; if (right < n && nums[right] > nums[largest]) largest = right; if (largest != i) { swap (nums[i], nums[largest]); heapify (nums, n, largest); } }void make_heap (vector<int >& nums) { int n = nums.size (); for (int i = n / 2 - 1 ; i >= 0 ; i--) heapify (nums, n, i); }vector<int > sortArray (vector<int >& nums) { make_heap (nums); for (int i = nums.size () - 1 ; i > 0 ; i--) { swap (nums[0 ], nums[i]); heapify (nums, i, 0 ); } return nums; }
希尔排序 思想:
使用一定的间隔(数组长度的一半)对数组进行分组,然后对每个分组进行插入排序
随着排序的进行,间隔逐步减小,直到间隔为1,最终完成排序
时间复杂度:n^1.3
设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void shellSort (vector<int >& arr) { int n = arr.size (); for (int gap = n / 2 ; gap > 0 ; gap /= 2 ) { for (int i = gap; i < n; i++) { int temp = arr[i]; int j; for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) { arr[j] = arr[j - gap]; } arr[j] = temp; } } }vector<int > sortArray (vector<int >& nums) { shellSort (nums); return nums; }
计数排序 时间复杂度:n+k,k为当前数组中的最大值
如果有负数还需要进行另外处理
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 std::vector<int > countingSort (std::vector<int >& nums) { int max_num = *std::max_element (nums.begin (), nums.end ()); std::vector<int > count (max_num + 1 , 0 ) ; for (int num : nums) { count[num]++; } std::vector<int > sortedArray (nums.size()) ; int index = 0 ; for (int i = 0 ; i <= max_num; ++i) { while (count[i] > 0 ) { sortedArray[index++] = i; count[i]--; } } return sortedArray; }vector<int > sortArray (vector<int >& nums) { return countingSort (nums); }