From: 爱编程的大丙 Author: 爱编程的大丙 原文链接:八大排序算法
一、冒泡排序
冒泡排序是稳定排序,原因是相等的值不交换,且只与相邻元素交换,不会打乱原有顺序
做法:每次都从待排序的部分挑选出一个最大值放在最后(挑选的方式是相邻元素都比较一次)
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 void bubble_sort (std::vector<int >& arr) { int length = arr.size () - 1 ; bool isSwap = false ; for (int i = 0 ; i < length; ++i) { isSwap = false ; for (int j = 0 ; j < length - i; ++j) { if (arr[j] > arr[j + 1 ]) { std::swap (arr[j], arr[j + 1 ]); isSwap = true ; } } if (!isSwap) { break ; } } }
二、选择排序
选择排序是不稳定排序 原因是会出现长距离交换,会打乱原有的顺序
做法:每次都从待排序的部分找到最大或最小值的位置然后交换放在相对最前的位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 void selected_sort (std::vector<int >& arr) { int length = arr.size () - 1 ; for (int i = 0 ; i < length; ++i) { int minPos = i; for (int j = i + 1 ; j <= length; ++j) { if (arr[minPos] > arr[j]) { minPos = j; } } if (minPos != i) { std::swap (arr[i], arr[minPos]); } } }
三、插入排序
插入排序是稳定排序, 原因是我们是根据待排序数组的顺序进行排序的,且与相邻元素比较,不会出现长距离交换的情况
做法:从待排序的数组中选出第一个元素A,让这个元素和已排好序的数组的最后一个进行比较B,如果A<B,则将A后移一位覆盖数据,从此往复,知道找到小于B的元素,然后将B插入到该位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void insert_sort (std::vector<int >& arr) { int length = arr.size () - 1 ; for (int i = 1 ; i <= length; ++i) { int temp = arr[i]; int j = i - 1 ; while (j >= 0 && arr[j] > temp) { arr[j + 1 ] = arr[j]; --j; } arr[j + 1 ] = temp; } }
四、 希尔排序
插入排序的优化版 但并不是稳定排序 原因是:交换的元素并不是相邻的元素,存在长距离交换的情况
做法:利用插入排序趋向排好序的数组排序速度快的特点,将一个大数组分为一个个小数组对其进行插入排序,又因为每一个小数组都趋向于有序,所以排序速度很快,最后会导致整个大数组都趋向于有序,这样就能提高排序速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void shell_sort (std::vector<int >& arr) { int length = arr.size (); for (int gap = length / 2 ; gap > 0 ; gap /= 2 ) { for (int i = gap; i < length; ++i) { int temp = arr[i]; int j = i - gap; while (j >= 0 && arr[j] > temp) { arr[j + gap] = arr[j]; j -= gap; } arr[j + gap] = temp; } } }
五、快速排序
快速排序是不稳定排序,原因是因为交换的元素并不是相邻的元素,会出现长距离交换元素的情况
做法:快速排序采用分治法,通常在中间取一个基准数,然后将比基准数小的元素放在左边,比基准数大的元素放在右边,如果左边的元素比基准数大,右边的元素比基准数小,则交换这两个元素的位置,直到所有元素都排好序,即left>right停止,然后重新划分子数组,通过不断递归的方式,当所有的子数组都排好序后,整个数组也就排好序了
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 void quick_sort (std::vector<int >& arr) { if (arr.empty ()) { return ; } quick_sort (arr, 0 , arr.size () - 1 ); } void quick_sort (std::vector<int >& arr, int left, int right) { if (left >= right) { return ; } int pivotValue = arr[left + (right - left) / 2 ]; int begin = left - 1 , end = right + 1 ; while (begin < end) { do { begin++; } while (arr[begin] < pivotValue); do { end--; } while (arr[end] > pivotValue); if (begin < end) { std::swap (arr[begin], arr[end]); } } quick_sort (arr, left, end); quick_sort (arr, end + 1 , right); }
六、归并排序
归并排序是稳定排序, 原因是:交换的是相邻的元素且是有序的,相等的元素不会交换位置
通过不断递归将数组分到不可再分为止,最后每一个子数组都是一个元素,然后将具有同一个分支的两个子数组进行合并,合并成一个有序数组最后,当所有的子数组都合并成一个有序数组后,整个数组也就排好序了
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 void merge_sort (std::vector<int >& arr) { if (arr.empty ()) { return ; } std::vector<int > temp (arr.size()) ; merge_sort (arr, temp, 0 , arr.size () - 1 ); } void merge_sort (std::vector<int >& arr, std::vector<int >& temp, int left, int right) { if (left >= right) { return ; } int mid = left + (right - left) / 2 ; merge_sort (arr, temp, left, mid); merge_sort (arr, temp, mid + 1 , right); int i = left, j = mid + 1 , index = 0 ; while (i <= mid && j <= right) { if (arr[i] < arr[j]) { temp[index++] = arr[i++]; } else { temp[index++] = arr[j++]; } } while (i <= mid) { temp[index++] = arr[i++]; } while (j <= right) { temp[index++] = arr[j++]; } for (int k = 0 ; k < index; ++k) { arr[left + k] = temp[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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 void head_sort (std::vector<int >& arr, int length, int parent) { int maxIndex = parent; int leftChild = 2 * parent + 1 ; int rightChild = 2 * parent + 2 ; if (leftChild < length && arr[leftChild] > arr[maxIndex]) { maxIndex = leftChild; } if (rightChild < length && arr[rightChild] > arr[maxIndex]) { maxIndex = rightChild; } if (maxIndex != parent) { std::swap (arr[parent], arr[maxIndex]); head_sort (arr, length, maxIndex); } } void head_sort (std::vector<int >& arr) { if (arr.empty ()) { return ; } for (int i = arr.size () / 2 - 1 ; i >= 0 ; --i) { head_sort (arr, arr.size (), i); } for (int i = arr.size () - 1 ; i > 0 ; --i) { std::swap (arr[0 ], arr[i]); head_sort (arr, i, 0 ); } }
推荐链接:六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序