冒泡排序,选择排序,插入排序(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_ */

猜你喜欢

转载自www.cnblogs.com/luyl/p/12377487.html