C++实现经典排序算法
/**---------------------------------------
* 文件名称: CSorter.h
* 功能描述: 排序算法的实现
* 创建标识: xad 2022/2/9
*
* 修改标识:
* 修改描述:
------------------------------------------**/
#ifndef CSORTER_SORTER_H
#define CSORTER_SORTER_H
class CSorter
{
public:
/**
* @brief 冒泡排序
*
* @param int arr[]
* @param int length
* @return void
*/
static void bubbleSort(int arr[], int length);
/**
* @brief 选择排序
*
* @param int arr[]
* @param int length
* @return void
*/
static void selectSort(int arr[], int length);
/**
* @brief 插入排序
*
* @param int arr[]
* @param int length
* @return void
*/
static void insertSort(int arr[], int length);
/**
* @brief 希尔排序
*
* @param int arr[]
* @param int length
* @return void
*/
static void shellSort(int arr[], int length);
/**
* @brief 快速排序
*
* @param int arr[]
* @param int start
* @param int end
* @return void
*/
static void quickSort(int arr[], int start, int end);
/**
* @brief 归并排序
*
* @param int arr[]
* @param int start
* @param int end
* @param int temp[]
* @return void
*/
static void mergeSort(int arr[], int start, int end, int temp[]);
/**
* @brief 堆排序
*
* @param int arr[]
* @param int length
* @return void
*/
static void heapSort(int arr[], int length);
protected:
private:
static void _swap(int* a, int* b);
// 快速排序使用
static int _partition(int arr[], int start, int end);
// 归并排序使用
static void _merge(int arr[], int start, int end, int mid, int temp[]);
// 堆排序使用
static void _adjust(int arr[], int index, int length);
};
#endif
#include "CSorter.h"
void CSorter::bubbleSort(int arr[], int length)
{
for (int i = 0; i < length;i++)
{
bool bFlag = false;
for (int j = length - 1; j > i;j--)
{
if (arr[j] < arr[j -1])
{
bFlag = true;
_swap(&arr[j], &arr[j - 1]);
}
}
if (!bFlag)
{
break;
}
}
}
void CSorter::selectSort(int arr[], int length)
{
//从小到大排序
// 选择排序通过减少交换次数来提升效率
for (int i = 0; i < length; ++i)
{
int nMinIndex = i;
for (int j = i; j < length; ++j)
{
if (arr[j] < arr[nMinIndex])
{
nMinIndex = j;
}
}
_swap(&arr[i], &arr[nMinIndex]);
}
}
// 插入排序
// 最好情况:原始序列正序,需要比较(n-1)次,移动2(n-1)次,时间复杂度O(n)
// 最坏情况:原始序列倒序,需要比较(n-1)(n+2)/2次(2~n求和值),移动(n-1)(n+4)/2次 ((2+1)~(n+1)求和值)
void CSorter::insertSort(int arr[], int length)
{
for (int i = 1; i < length; ++i)
{
if (arr[i] < arr[i - 1])
{
//找到合适的插入位置
int temp = arr[i];
int j;
for (j = i - 1; j >= 0 && arr[j] > temp; --j)
{
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
}
}
void CSorter::shellSort(int arr[], int length)
{
int increase = length;
do {
increase = increase / 3 + 1;
for (int i = 0; i < increase; ++i)
{
for (int j = i + increase; j < length; j += increase)
{
if (arr[j] < arr[j - increase])
{
int temp = arr[j];
int k;
for (k = j - increase; k >= 0 && arr[k] > temp; k -= increase)
{
arr[k + increase] = arr[k];
}
arr[k + increase] = temp;
}
}
}
} while (increase > 1);
}
void CSorter::quickSort(int arr[], int start, int end)
{
if (start >= end) {
return;
}
int pivotPos = _partition(arr, start, end); //将大的数值排在pivotPos右边,将小的数值排在左边
quickSort(arr, start, pivotPos - 1);
quickSort(arr, pivotPos + 1, end);
}
void CSorter::mergeSort(int arr[], int start, int end, int temp[])
{
if (start >= end) {
return;
}
int mid = start + (end - start) / 2;
mergeSort(arr, start, mid, temp);
mergeSort(arr, mid + 1, end, temp);
_merge(arr, start, end, mid, temp);
}
void CSorter::heapSort(int arr[], int length)
{
// 初始化堆,大顶堆
for (int i = length / 2 - 1; i >= 0; --i) {
_adjust(arr, i, length);
}
// 交换堆顶元素和最后一个元素
for (int i = length - 1; i >= 0; --i) {
_swap(&arr[0], &arr[i]);
_adjust(arr, 0, i);
}
}
void CSorter::_swap(int * a, int * b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int CSorter::_partition(int arr[], int start, int end)
{
int nPosValue = arr[start];
int nPosIndex = start;
int ni = start, nj = end;
while (ni < nj)
{
while (arr[nj] > nPosValue)
{
nj--;
}
while (arr[ni] <= nPosValue)
{
ni++;
}
if (ni >= nj)
{
break;
}
_swap(&arr[ni], &arr[nj]);
}
arr[nPosIndex] = arr[nj];
arr[nj] = nPosValue;
return nj;
}
void CSorter::_merge(int arr[], int start, int end, int mid, int temp[])
{
int i_start = start;
int j_start = mid + 1;
int i_end = mid;
int j_end = end;
int pos = start;
while (i_start <= i_end && j_start <= j_end) {
if (arr[i_start] < arr[j_start]) {
temp[pos] = arr[i_start];
i_start++;
pos++;
}
else {
temp[pos] = arr[j_start];
j_start++;
pos++;
}
}
while (i_start <= i_end) {
temp[pos] = arr[i_start];
i_start++;
pos++;
}
while (j_start <= j_end) {
temp[pos] = arr[j_start];
j_start++;
pos++;
}
for (int i = start; i <= end; ++i) {
arr[i] = temp[i];
}
}
void CSorter::_adjust(int arr[], int index, int length)
{
while ((2 * index + 1) < length) {
int lchild = 2 * index + 1;
int rchild = lchild + 1;
int maxChild = (rchild < length && arr[rchild] > arr[lchild]) ? rchild : lchild;
if (arr[index] >= arr[maxChild]) break;
_swap(&arr[index], &arr[maxChild]);
index = maxChild;
}
}
/**---------------------------------------
* 文件名称: TestCSorter.cpp
* 功能描述: 测试排序算法
* 创建标识: xad 2022/2/9
*
* 修改标识:
* 修改描述:
------------------------------------------**/
#include<iostream>
#include <string>
#include "CSorter.h"
#include <sys/timeb.h>
#include <time.h>
const int MAX_SIZE = 10000;
void printArray(int arr[], int length);
long getSystemTime(void);
void test_07(void);
int main()
{
test_07();
system("pause");
return 0;
}
void test_07(void)
{
int* arr = new int[MAX_SIZE];
std::srand((unsigned int)time(nullptr));
for (int i = 0; i < MAX_SIZE; ++i) {
arr[i] = std::rand() % MAX_SIZE;
}
std::cout << "排序前:" << std::endl;
// printArray(arr, MAX_SIZE);
long t_start = getSystemTime();
CSorter::bubbleSort(arr, MAX_SIZE);
long t_end = getSystemTime();
std::cout << "冒泡排序" << MAX_SIZE << "个元素,所需时间:" << (t_end - t_start) << std::endl;
std::cout << "排序后:" << std::endl;
// printArray(arr, MAX_SIZE);
for (int i = 0; i < MAX_SIZE; ++i) {
arr[i] = std::rand() % MAX_SIZE;
}
std::cout << "排序前:" << std::endl;
// printArray(arr, MAX_SIZE);
t_start = getSystemTime();
CSorter::selectSort(arr, MAX_SIZE);
t_end = getSystemTime();
std::cout << "选择排序" << MAX_SIZE << "个元素,所需时间:" << (t_end - t_start) << std::endl;
std::cout << "排序后:" << std::endl;
// printArray(arr, MAX_SIZE);
for (int i = 0; i < MAX_SIZE; ++i) {
arr[i] = std::rand() % MAX_SIZE;
}
std::cout << "排序前:" << std::endl;
// printArray(arr, MAX_SIZE);
t_start = getSystemTime();
CSorter::insertSort(arr, MAX_SIZE);
t_end = getSystemTime();
std::cout << "插入排序" << MAX_SIZE << "个元素,所需时间:" << (t_end - t_start) << std::endl;
std::cout << "排序后:" << std::endl;
// printArray(arr, MAX_SIZE);
for (int i = 0; i < MAX_SIZE; ++i) {
arr[i] = std::rand() % MAX_SIZE;
}
std::cout << "排序前:" << std::endl;
// printArray(arr, MAX_SIZE);
t_start = getSystemTime();
CSorter::shellSort(arr, MAX_SIZE);
t_end = getSystemTime();
std::cout << "希尔排序" << MAX_SIZE << "个元素,所需时间:" << (t_end - t_start) << std::endl;
std::cout << "排序后:" << std::endl;
// printArray(arr, MAX_SIZE);
for (int i = 0; i < MAX_SIZE; ++i) {
arr[i] = std::rand() % MAX_SIZE;
}
std::cout << "排序前:" << std::endl;
// printArray(arr, MAX_SIZE);
t_start = getSystemTime();
CSorter::quickSort(arr, 0, MAX_SIZE - 1);
t_end = getSystemTime();
std::cout << "快速排序" << MAX_SIZE << "个元素,所需时间:" << (t_end - t_start) << std::endl;
std::cout << "排序后:" << std::endl;
// printArray(arr, MAX_SIZE);
for (int i = 0; i < MAX_SIZE; ++i) {
arr[i] = std::rand() % MAX_SIZE;
}
int* temp = new int[MAX_SIZE];
std::cout << "排序前:" << std::endl;
// printArray(arr, MAX_SIZE);
t_start = getSystemTime();
CSorter::mergeSort(arr, 0, MAX_SIZE - 1, temp);
t_end = getSystemTime();
std::cout << "归并排序" << MAX_SIZE << "个元素,所需时间:" << (t_end - t_start) << std::endl;
std::cout << "排序后:" << std::endl;
// printArray(arr, MAX_SIZE);
for (int i = 0; i < MAX_SIZE; ++i) {
arr[i] = std::rand() % MAX_SIZE;
}
std::cout << "排序前:" << std::endl;
// printArray(arr, MAX_SIZE);
t_start = getSystemTime();
CSorter::heapSort(arr, MAX_SIZE);
t_end = getSystemTime();
std::cout << "堆排序" << MAX_SIZE << "个元素,所需时间:" << (t_end - t_start) << std::endl;
std::cout << "排序后:" << std::endl;
// printArray(arr, MAX_SIZE);
delete[] temp;
delete[] arr;
}
long getSystemTime()
{
struct timeb tb {};
ftime(&tb);
return tb.time * 1000 + tb.millitm;
}
void printArray(int arr[], int length)
{
for (int i = 0; i < length; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}