排序过程中,后面的排序不会更改之前已经排序后的数据的顺序,则称这种排序算法是稳定的;否则称为不稳定的。
冒泡还有一种优化,面试时说出来会加分冒泡排序的优化
相邻元素两两比较,反序则交换;
每一轮完毕,将最大元素排在数组顶端;
时间复杂度:o(n^2)
vector<int> sortSolution::bubbleSort(vector<int>& arr) { int n = arr.size(); for(int i = n - 1; i >= 0; --i) { int cnt = 0; for(int j = 0; j < i; ++j) { if(arr[j] > arr[j + 1]) { swap(arr[j], arr[j + 1]); cnt++; } } if(cnt == 0) break; } return arr; }
每一趟选出一个最小值,放到前面
时间复杂度:o(n^2)
vector<int> sortSolution::selectSort(vector<int>& arr) { int n = arr.size(); for(int i = 0; i < n - 1; ++i) { int min = i; for(int j = i; j < n; ++j) { if(arr[j] < arr[min]) { min = j; } } if(min != i) { swap(arr[i], arr[min]); } } return arr; }
不断地从后面选一个数,然后插入到前面已经有序的序列里;
时间复杂度:o(n^2)
vector<int> sortSolution::insertSort(vector<int>& arr) { int n = arr.size(); for(int i = 1; i < n; ++i) { while(i > 0) { if(arr[i] < arr[i - 1]) { swap(arr[i], arr[i - 1]); i--; } else break; } } return arr; }
是一种分组插入排序算法
时间复杂度:o(nlogn) ~ o(n^2)
class Solution { public: vector<int> sortSolution::shelleSort(vector<int>& arr) { int n = arr.size(); for(int gap = n / 2; gap > 0; gap /= 2) { for(int i = gap; i < n; ++i) { int tmp = arr[i]; int j = i - gap; while(j >= 0 && tmp < arr[j]) { arr[j + gap] = arr[j]; j -= gap; } arr[j + gap] = tmp; } } return arr; } };
指定第一个数为mid_value,排序使得mid_value左边的数比mid_value小,右边的数比mid_value大,然后分别对左边和右边进行递归排序。
class Solution { public: void sortSolution::quickSort(vector<int>& arr, int start, int end) { if(start >= end) { return; } int midVal = arr[start]; int low = start; int high = end; while(low < high) { while(low < high && arr[high] >= midbVal) { high--; } arr[low] = arr[high]; while(low < high && arr[low] <= midVal) { low++; } arr[high] = arr[low]; } arr[low] = midVal; quickSort(arr, start, low - 1); quickSort(arr, low + 1, end); } };
拆分到单个元素,然后两个两个往上进行递归合并。设置left 和right两个游标,进行合并。
时间复杂度:o(nlogn)
class Solution { public: void sortSolution::merge(vector<int> &arr, int left, int mid, int right) { std::vector<int> tmp(right - left + 1); int i = left, j = mid + 1, k = 0; while(i <= mid && j <= right) { tmp[k++] = arr[i] > arr[j] ? arr[i++] : arr[j++]; } while(i <= mid) { tmp[k++] = arr[i++]; } while (j <= right) { tmp[k++] = arr[j++]; } for(int p = 0; p < tmp.size(); ++p) { arr[left + p] = tmp[p]; } } void sortSolution::mergeSort(vector<int>& arr, int left, int right) { if(left >= right) { return; } int mid = (left + right) >> 1; mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); merge(arr, left, mid, right); } };
构造堆:从小堆到大堆,先看最后一个非叶子节点,从下往上
建堆的时间复杂度为:o(n)
时间复杂度 : o(nlogn)
下标为i的节点的父节点下表:(i-1)/2
下表为i的节点的左孩子下表:i*2+1
下表为i的节点的右孩子下表:i*2+2
void sortSolution::maxHeap(vector<int>& arr, int i, int heapSize) { int l = i * 2 + 1; int r = l + 1; int largest = i; if(l < heapSize && arr[l] > arr[largest]) { largest = l; } if(r < heapSize && arr[r] > arr[largest]) { largest = r; } if(largest != i) { swap(arr[i], arr[largest]); maxHeap(arr, largest, heapSize); } } void sortSolution::buildMaxHeap(vector<int>& arr) { for(int i = arr.size() / 2 - 1; i >= 0; --i) { maxHeap(arr, i, arr.size()); } } void sortSolution::heapSort(vector<int>& arr) { buildMaxHeap(arr); for(int i = arr.size() - 1; i > 0; --i) { swap(arr[0], arr[i]); maxHeap(arr, 0, i); } }