c++11
在ubuntu 18.04上通过编译和调试
以下代码均是从小到大排序
冒泡排序
1 /* 2 * BubbleSort.h 3 * 冒泡排序 4 * Created on: 2020年2月10日 5 * Author: LuYonglei 6 */ 7 8 #ifndef SRC_BUBBLESORT_H_ 9 #define SRC_BUBBLESORT_H_ 10 #include <vector> 11 using namespace std; 12 13 #if 0 14 15 template<typename T> 16 void bubbleSort(vector<T> &arr) { 17 //冒泡排序,从小到大(数组存在提前有序的情况下可以优化,但此情况出现概率较低) 18 for (int end = arr.size() - 1; end > 0; end--) { 19 //外层循环控制遍历次数 20 bool sorted = true; //优化添加的标记 21 for (int begin = 1; begin <= end; begin++) { 22 //内层循环控制比较和交换次数 23 if (arr[begin] < arr[begin - 1]) { 24 swap(arr[begin], arr[begin - 1]); 25 sorted = false; 26 } 27 } 28 //若已经有序,则提前退出排序 29 if (sorted) 30 break; 31 } 32 } 33 #else 34 35 template<typename T> 36 void bubbleSort(vector<T> &arr) { 37 //冒泡排序,从小到大(如果序列尾部局部有序,可以记录最后一次交换位置,减少比较次数) 38 for (int end = arr.size() - 1; end > 0; end--) { 39 //外层循环控制遍历次数 40 int sortedIndex = 0; //优化添加的索引(此索引不可以随便设置,为数据完全有序做准备,若完全有序会提前退出) 41 for (int begin = 1; begin <= end; begin++) { 42 //内层循环控制比较和交换次数 43 if (arr[begin] < arr[begin - 1]) { 44 swap(arr[begin], arr[begin - 1]); 45 sortedIndex = begin; 46 } 47 } 48 //记录最后一次交换位置,减少比较次数 49 end = sortedIndex; 50 } 51 } 52 53 #endif 54 55 #endif /* SRC_BUBBLESORT_H_ */
选择排序
/* * SelectionSort.h * 选择排序(选择排序交换次数远远小于冒泡排序,所以平均性能比冒泡排序要好) * Created on: 2020年2月10日 * Author: LuYonglei */ #ifndef SRC_SELECTIONSORT_H_ #define SRC_SELECTIONSORT_H_ #include <vector> using namespace std; #if 1 template<typename T> void selectionSort(vector<T> &arr) { //从序列中选择最大的元素,与末尾元素交换位置 for (int end = arr.size() - 1; end > 0; end--) { int maxIndex = 0; //最大元素的索引 for (int begin = 0; begin <= end; begin++) { if (arr[begin] >= arr[maxIndex]) maxIndex = begin; //保留最大元素位置的索引(要保证排序算法的稳定性,需要加=) } swap(arr[maxIndex], arr[end]); //选择最大的元素,与末尾元素交换位置 } } #else //利用堆来选择最值,配合排序算法可以降低算法复杂度,所以衍生出了堆排序 #endif #endif /* SRC_SELECTIONSORT_H_ */
插入排序
插入排序使用的BinarySearch.h
/* * BinarySearch.h * 二分查找 * 数组取值范围尽量保证左闭右开,这样end-begin=size,编码比较方便 * Created on: 2020年2月11日 * Author: LuYonglei */ #ifndef SRC_BINARYSEARCH_H_ #define SRC_BINARYSEARCH_H_ #include <vector> using namespace std; #define ELEMENT_NOT_FIND -1 //查找value在有序数组arr中的位置 template<typename T> int indexOf(const vector<T> &arr, int size, T value) { int arraySize = arr.size(); if (arraySize == 0 || size <= 0 || arraySize < size) return ELEMENT_NOT_FIND; int begin = 0; //最前面元素的索引 int end = size; //最后一个元素索引的下一个 while (begin < end) { int middle = (begin + end) / 2; if (value < arr[middle]) { end = middle; } else if (value > arr[middle]) { begin = middle + 1; } else { //value==arr[mid] return middle; } } return ELEMENT_NOT_FIND; } //查找value在有序数组arr中待插入的位置 //有序数组中第一个大于value的位置 template<typename T> int indexOfInsertion(const vector<T> &arr, int size, T value) { //为了保证二分查找后再插入的稳定性 int arraySize = arr.size(); if (arraySize == 0 || size <= 0 || arraySize < size) return ELEMENT_NOT_FIND; int begin = 0; //最前面元素的索引 int end = size; //最后一个元素索引的下一个 while (begin < end) { int middle = (begin + end) / 2; if (value < arr[middle]) { end = middle; } else { //value >= arr[middle] begin = middle + 1; } } //此时begin==end return begin; } #endif /* SRC_BINARYSEARCH_H_ */
以下是插入排序的具体实现
/* * InsertionSort.h * 插入排序 * Created on: 2020年2月11日 * Author: LuYonglei */ #ifndef SRC_INSERTIONSORT_H_ #define SRC_INSERTIONSORT_H_ #include <vector> #include "BinarySearch.h" using namespace std; #if 0 template<typename T> void insertionSort(vector<T> &arr) { for (size_t begin = 1; begin < arr.size(); begin++) { int end = begin; //如果end元素小于end-1元素就交换位置,否则就跳出循环 while (end > 0 && (arr[end] < arr[end - 1])) { swap(arr[end], arr[end - 1]); end--; } } } #elif 0 //优化,将交换改为挪动 template<typename T> void insertionSort(vector<T> &arr) { for (size_t begin = 1; begin < arr.size(); begin++) { int end = begin; T value = arr[end]; //如果end元素小于end-1元素就用end-1元素覆盖end元素,否则就跳出循环 while (end > 0 && (value < arr[end - 1])) { arr[end] = arr[end - 1]; end--; } arr[end] = value; } } #else //对已排序部分进行二分搜索优化(在挪动的基础上再优化比较次数) template<typename T> void insertionSort(vector<T> &arr) { for (size_t begin = 1; begin < arr.size(); begin++) { T value = arr[begin]; //保存要插入的值 int index = indexOfInsertion(arr, begin, value); //得到待插入位置 //移动元素 for (int i = begin; i > index; i--) { arr[i] = arr[i - 1]; } arr[index] = value; } } #endif #endif /* SRC_INSERTIONSORT_H_ */
堆排序
/* * HeapSort.h * 堆排序 * Created on: 2020年2月10日 * Author: LuYonglei */ #ifndef SRC_HEAPSORT_H_ #define SRC_HEAPSORT_H_ #include <vector> using namespace std; template<typename T> void siftDown(vector<T> &arr, int index, int heapSize) { //下滤 T element = arr[index]; //保存父节点的元素 int half = heapSize / 2; while (index < half) { //index必须是叶子节点 int childIndex = 2 * index + 1; //默认是左子节点 T childElement = arr[childIndex]; //左子节点的元素 int rightIndex = childIndex + 1; //右子节点下标 //若右子节点的元素大于左子节点的元素, if (rightIndex < heapSize && arr[rightIndex] > childElement) { childElement = arr[rightIndex]; childIndex = rightIndex; } //如果大于等于子节点,就跳出循环 if (element >= childElement) break; //如果父节点元素小于子节点元素,用子节点元素覆盖父节点元素 arr[index] = childElement; index = childIndex; } arr[index] = element; } //1.对序列原地建堆(heapify) //2. // 将0号元素与末尾元素交换位置 // 堆的size-1 // 对0号元素进行下滤(siftdown) // 重复2中的以上操作,直至size变为1 template<typename T> void heapSort(vector<T> &arr) { int heapSize = arr.size(); //原地建堆,对所有元素进行下滤 for (int i = heapSize / 2 - 1; i >= 0; i--) siftDown(arr, i, heapSize); while (heapSize > 1) { //交换堆顶元素和堆尾部元素,堆大小减小1 swap(arr[0], arr[--heapSize]); //对堆顶元素进行下滤 siftDown(arr, 0, heapSize); } } #endif /* SRC_HEAPSORT_H_ */
main函数
/* * main.cpp * * Created on: 2020年2月10日 * Author: LuYonglei */ #include <iostream> #include <vector> #include "MyTemplate.h" #include "BubbleSort.h" #include "SelectionSort.h" #include "HeapSort.h" #include "InsertionSort.h" using namespace std; int main(int argc, char **argv) { vector<int> arr; int a[] = { 1, 2, 3, 6, 8, 19, 10, 3, 0, 0, 100, -1 }; for (size_t i = 0; i < sizeof(a) / sizeof(int); i++) arr.push_back(a[i]); // bubbleSort(arr); // selectionSort(arr); // heapSort(arr); insertionSort(arr); print(arr); }