冒泡排序,选择排序,插入排序(c++算法优化版本)
冒泡排序
/* * BubbleSort.h * 冒泡排序 * Created on: 2020年2月10日 * Author: LuYonglei */ #ifndef SRC_BUBBLESORT_H_ #define SRC_BUBBLESORT_H_ #include <vector> using namespace std; #if 0 template<typename T> void bubbleSort(vector<T> &arr) { //冒泡排序,从小到大(数组存在提前有序的情况下可以优化,但此情况出现概率较低) for (int end = arr.size() - 1; end > 0; end--) { //外层循环控制遍历次数 bool sorted = true; //优化添加的标记 for (int begin = 1; begin <= end; begin++) { //内层循环控制比较和交换次数 if (arr[begin] < arr[begin - 1]) { swap(arr[begin], arr[begin - 1]); sorted = false; } } //若已经有序,则提前退出排序 if (sorted) break; } } #else template<typename T> void bubbleSort(vector<T> &arr) { //冒泡排序,从小到大(如果序列尾部局部有序,可以记录最后一次交换位置,减少比较次数) for (int end = arr.size() - 1; end > 0; end--) { //外层循环控制遍历次数 int sortedIndex = 0; //优化添加的索引(此索引不可以随便设置,为数据完全有序做准备,若完全有序会提前退出) for (int begin = 1; begin <= end; begin++) { //内层循环控制比较和交换次数 if (arr[begin] < arr[begin - 1]) { swap(arr[begin], arr[begin - 1]); sortedIndex = begin; } } //记录最后一次交换位置,减少比较次数 end = sortedIndex; } } #endif #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_ */
插入排序
/* * 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_ */
插入排序优化中使用到的二分搜索
/* * 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_ */