8种基本排序算法总结如下
各种演示代码,通过一个SortTest类来掩饰,在VS2010里面运行正常。最后的比较没有编写代码,并且一些输入信息没有做判断,只是实现了基本的排序功能
SortTest类代码如下,
SortTest.h
#pragma once
#include <vector>
using namespace std;
struct DigitInfo
{
int digit; // 随机数
int index; // 随机数的索引
};
class SortTest
{
public:
SortTest(void);
SortTest(int count, int start, int end);
~SortTest(void);
public:
int count;
int start;
int end;
DigitInfo *digitArray; // 随机生成数存储结构
bool genRandDigits(); // 生成随机数,存储在digitVec里面
void printDigitArray(); // 输出结果
bool bubbleSort(); // 冒泡排序
bool quickSort(); // 快速排序
void swap(int i, int j); // 交换两个元素的数据
bool quickSort_ChangePos(int left, int right); // 快速排序要用到的递归调用函数
bool directInsertSort(); // 直接插入排序
bool shellSort(); // 希尔排序
bool simpleSelectSort(); // 选择排序
bool maxHeapSort(); // 堆排序(小顶堆)
bool maxHeapAjust(int length, int nodeNum); // 调整大顶推
bool merge(int left, int mid, int right, DigitInfo *pDigitInfo);
bool merge(int left, int right, DigitInfo *pDigitInfo);
bool mergeSort(); // 归并排序算法
int getMaxNum(); // 获取digitArray里面最大的数
int getDigitCapacity(); // 获取最大数字的位数
bool baseSort(); // 通过位数,将
bool baseDigitSort(); // 基数排序算法
bool compareSort(); // 比较各种算法所用时间,并且输出时间
};
SortTest.cpp
#include "SortTest.h"
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <vector>
#include <queue>
#include "math.h"
using namespace std;
SortTest::SortTest(void)
{
digitArray = NULL;
}
SortTest::SortTest(int count, int start, int end)
{
digitArray = NULL;
this->count = count;
this->start = start;
this->end = end;
}
SortTest::~SortTest(void)
{
if (digitArray != NULL)
{
delete[] digitArray;
}
}
bool SortTest::genRandDigits() // 生成随机数,存储在digitVec里面
{
if ( digitArray != nullptr)
{
delete[] digitArray;
}
srand((int)time(NULL)); //每次执行种子不同,生成不同的随机数
digitArray = new DigitInfo[count];
for(int i = 0; i < count; i ++)
{
int tmpRandDigit = rand() % ( end - start ) + start;
struct DigitInfo digitInfo;
digitInfo.digit = tmpRandDigit;
digitInfo.index = i;
digitArray[i] = digitInfo;
}
cout << "原始的排列顺序为以下:" << endl;
printDigitArray();
return true;
}
// 输出
void SortTest::printDigitArray()
{
for (int i = 0; i < count; i ++)
{
if( i % 10 == 0 && i != 0)
cout << endl;
cout << digitArray[i].digit << "-[" << digitArray[i].index << "]" << "\t";
}
}
// 冒泡排序
bool SortTest::bubbleSort() // 冒泡排序
{
// 产生随机数
genRandDigits();
for(int i = 0; i < count - 1; i ++) // 冒泡排序的趟数
{
bool flag = true;
for( int j = 0; j < count - 1 - i; j ++) // 每趟比较的次数
{
if ( digitArray[j].digit > digitArray[j + 1].digit )
{
swap(j, j + 1);
flag = false;
}
}
if (flag)
break;
}
cout << "冒泡排序后的顺序是" << endl;
printDigitArray();
cout << endl;
return true;
}
// 快速排序
bool SortTest::quickSort()
{
genRandDigits();
quickSort_ChangePos(0, count - 1);
cout<< "快排之后的顺序:" << endl;
printDigitArray();
cout << endl;
return true;
}
// 交换两个元素的值
void SortTest::swap(int i, int j)
{
struct DigitInfo digitInfo;
//digitInfo.digit = digitArray[i].digit;
//digitInfo.index = digitArray[i].index;
//digitArray[i].digit = digitArray[j].digit;
//digitArray[i].index = digitArray[j].index;
//digitArray[j].digit = digitInfo.digit;
//digitArray[j].index = digitInfo.index;
digitInfo = digitArray[i];
digitArray[i] = digitArray[j];
digitArray[j] = digitInfo;
}
// 递归调用,用于快速排序
bool SortTest::quickSort_ChangePos(int left, int right)
{
int baseNum = digitArray[left].digit; // 基准值,就取第一个
int baseIndex = left;
int tmpStart = left;
int tmpEnd = right;
if(left >= right)
return true;
while( tmpStart < tmpEnd )
{
if ( ( digitArray[tmpStart].digit > digitArray[tmpEnd].digit ) && ( tmpStart == baseIndex ) )
{
swap( tmpStart, tmpEnd );
baseIndex = tmpEnd;
tmpStart ++;
}
else if ( ( digitArray[tmpStart].digit > digitArray[tmpEnd].digit ) && ( tmpEnd == baseIndex ) )
{
swap( tmpStart, tmpEnd );
baseIndex = tmpStart;
tmpEnd --;
}
else if ( ( digitArray[tmpStart].digit <= digitArray[tmpEnd].digit ) && ( tmpStart == baseIndex ) )
{
tmpEnd --;
}
else if ( ( digitArray[tmpStart].digit <= digitArray[tmpEnd].digit ) && ( tmpEnd == baseIndex ) )
{
tmpStart ++;
}
}
quickSort_ChangePos(left, baseIndex - 1); // 左边
quickSort_ChangePos(baseIndex + 1, right); // 右边
return false;
}
// 直接插入排序
bool SortTest::directInsertSort()
{
// 产生随机数
genRandDigits();
for( int i = 1; i < count; i ++ )
{
if ( digitArray[i].digit < digitArray[i - 1].digit ) // 如果每次这个条件都不成立,则时间复杂度为O(n)
{
int tmpDigit = digitArray[i].digit;
struct DigitInfo tmpDigitInfo = digitArray[i];
int j = i - 1;
for (; j >= 0 && digitArray[j].digit > tmpDigitInfo.digit; j -- )
{
digitArray[j + 1] = digitArray[j];
}
digitArray[j + 1] = tmpDigitInfo;
}
}
cout << "直接插入排序排序后的顺序是" << endl;
printDigitArray();
cout << endl;
return true;
}
// 希尔排序
bool SortTest::shellSort()
{
genRandDigits();
int increment = count / 2;
while ( increment > 0 ) // 排序的趟数
{
for ( int i = 0; i < increment; i ++ ) // 分的组数
{
for ( int j = i + increment; j < count ; j += increment) // 每组内需排序的元素个数
{
DigitInfo tmpDigitInfo = digitArray[j];
int k = j - increment;
for (; k >= 0 && digitArray[k].digit > tmpDigitInfo.digit; k -= increment) // 每个元素的插入过程,查找的次数
{
digitArray[k + increment] = digitArray[k];
}
digitArray[k + increment] = tmpDigitInfo;
printDigitArray();
cout << "………………第" << j << "个元素排完了………………" << endl;
}
printDigitArray();
cout << "***************一组排完了***************" << endl;
}
cout << "===============一趟排完了===============" << endl;
increment /= 2;
}
cout << "希尔排序之后的顺序为:" << endl;
printDigitArray();
cout << endl;
return true;
}
// 选择排序算法
bool SortTest::simpleSelectSort()
{
genRandDigits();
int minIndex = 0; // 最小值的索引
for ( int i = 0; i < count; i ++ )
{
minIndex = i;
for (int j = i; j < count; j ++ )
{
if( digitArray[j].digit < digitArray[minIndex].digit )
minIndex = j;
}
swap(i, minIndex); // 将最小元素和第i个元素交换
}
cout << "简单选择排序之后的顺序为:" << endl;
printDigitArray();
cout << endl;
return true;
}
// 堆排序(小顶堆)
bool SortTest::maxHeapSort()
{
genRandDigits();
for ( int i = count; i > 0; i -- )
{
for (int j = i / 2 - 1; j >= 0; j -- )
{
maxHeapAjust(i, j);
}
swap(0,i - 1);
}
cout << "堆排序(大顶堆)后的顺序为:" << endl;
printDigitArray();
cout << endl;
return true;
}
// 调整至大顶堆
bool SortTest::maxHeapAjust(int length, int nodeNum)
{
int leftChildNum = nodeNum * 2 + 1;
int rightChildNum = nodeNum * 2 + 2;
int maxIndex = nodeNum; // 临时变量用于存储左右孩子里面最大的值的nodeNum
if ( leftChildNum <= length - 1 && digitArray[leftChildNum].digit > digitArray[maxIndex].digit )
{
maxIndex = leftChildNum;
}
if ( rightChildNum <= length - 1 && digitArray[rightChildNum].digit > digitArray[maxIndex].digit )
{
maxIndex = rightChildNum;
}
if ( maxIndex != nodeNum)
{
swap(nodeNum, maxIndex);
maxHeapAjust(length, maxIndex);
}
return false;
}
// 将以left开始leftSize和以right开始rightSize为大小的有序合并给pDigitInfo指向的数组中
bool SortTest::merge(int left, int mid, int right, DigitInfo *pDigitInfo)
{
int leftIndex = left;
int rightIndex = mid + 1;
int totalIndex = left;
while ( leftIndex != mid + 1 && rightIndex != right + 1)
{
// 注意必须有等号,因为和右边的一样的话优先选左边的
if ( digitArray[leftIndex].digit <= digitArray[rightIndex].digit)
{
pDigitInfo[totalIndex ++] = digitArray[leftIndex ++];
}
else
{
pDigitInfo[totalIndex ++] = digitArray[rightIndex ++];
}
}
while ( leftIndex < mid + 1 )
{
pDigitInfo[totalIndex ++] = digitArray[leftIndex ++];
}
while( rightIndex < right + 1 )
{
pDigitInfo[totalIndex ++] = digitArray[rightIndex ++];
}
for (int i = left; i <= right; i ++)
{
digitArray[i] = pDigitInfo[i];
}
//cout << "合并之后:" << endl;
//printDigitArray();
//cout << endl;
return true;
}
bool SortTest::merge(int left, int right, DigitInfo *pDigitInfo)
{
if (left >= right)
{
return false;
}
int mid = ( left + right ) / 2;
merge(left, mid, pDigitInfo);
merge(mid + 1, right, pDigitInfo);
merge(left, mid, right, pDigitInfo);
return true;
}
// 归并排序算法
bool SortTest::mergeSort()
{
DigitInfo *tmpDigitArray = new DigitInfo[count];
genRandDigits();
merge(0, count - 1, tmpDigitArray);
delete[] tmpDigitArray;
cout << "归并排序后的顺序:" << endl;
printDigitArray();
cout << endl;
return true;
}
// 获取digitArray里面最大的数
int SortTest::getMaxNum()
{
int maxNum = 0;
for (int i = 0; i < count; i ++)
{
if(digitArray[i].digit > maxNum)
maxNum = digitArray[i].digit;
}
return maxNum;
}
// 获取最大数字的位数
int SortTest::getDigitCapacity()
{
int loopTimes = 0;
int maxNum = getMaxNum();
while (maxNum > 0)
{
maxNum /= 10;
loopTimes ++;
}
return loopTimes;
}
//
bool SortTest::baseSort()
{
int digitCapacity = getDigitCapacity();
for (int i = 0; i < digitCapacity; i ++)
{
vector<DigitInfo> bukets[10]; // 10个桶
int numOfBucket = 0;
for (int j = 0; j < count; j ++)
{
numOfBucket =( digitArray[j].digit / (int) pow((double)10, (double)i) ) % 10; // 获取所应进入的桶的号码
bukets[numOfBucket].push_back(digitArray[j]); // 装入桶中
}
int indexOfArray = 0;
for (int k = 0; k < 10; k ++) // 从桶中放回到digitArray里面
{
//if(!bukets[k].empty())
//{
// vector<DigitInfo>::iterator it = bukets[k].begin();
// while (it != bukets[k].end())
// {
// /*digitArray[indexOfArray] = *it;
// it ++;*/
// cout << it->digit << "\t";
// it ++;
// }
//}
if(!bukets[k].empty())
{
vector<DigitInfo>::iterator it = bukets[k].begin();
while (it != bukets[k].end())
{
digitArray[indexOfArray ++] = *it;
it ++;
}
}
}
}
return true;
}
// 基数排序算法
bool SortTest::baseDigitSort()
{
genRandDigits();
baseSort();
cout << "基数排序后的顺序:" << endl;
printDigitArray();
cout << endl;
return true;
}
// 比较各种算法
bool SortTest::compareSort()
{
DigitInfo *p = new DigitInfo[10];
genRandDigits();
// 把生成的数组存起来
for (int i = 0; i < count; i ++)
{
p[i] = digitArray[i];
}
cout << "原始数组顺序:" << endl;
printDigitArray();
cout << "冒泡排序后的顺序为:" << endl;
return true;
}
主函数
main.cpp
#include <iostream>
#include "stdlib.h"
#include "SortTest.h"
using namespace std;
void printMenu(int count, int start, int end)
{
cout << "[0] 设置随机数的数量个数,目前数量为:" << count << endl;
cout << "[1] 设置随机数的范围,目前范围为[" << start << "," << end << "]" << endl;
cout << "[2] 交换排序算法" << endl;
cout << "[3] 插入排序算法" << endl;
cout << "[4] 选择排序算法" << endl;
cout << "[5] 归并排序算法" << endl;
cout << "[6] 基数排序算法" << endl;
cout << "请选择:" << endl;
}
// 选择排序菜单
void printSwapSort()
{
cout << "[0] 冒泡排序" << endl;
cout << "[1] 快速排序" << endl;
cout << "请选择:" << endl;
}
// 插入排序菜单
void printInsertSort()
{
cout << "[0] 直接插入排序" << endl;
cout << "[1] 希尔排序" << endl;
cout << "请选择:" << endl;
}
// 选择排序菜单
void printSelectSort()
{
cout << "[0] 简单选择排序" << endl;
cout << "[1] 树形排序(堆排序)" << endl;
cout << "请选择:" << endl;
}
// 处理交换排序
void swapSortHandler(int count, int start, int end)
{
printSwapSort();
int subChoice = 0;
cin >> subChoice;
switch( subChoice )
{
case 0:
{
SortTest sortTest(count, start, end);
sortTest.bubbleSort();
}
break;
case 1:
{
SortTest sortTest(count, start, end);
sortTest.quickSort();
}
break;
default:
break;
}
}
// 处理插入排序
void insertSortHandler(int count, int start, int end)
{
printInsertSort();
int subChoice = 0;
cin >> subChoice;
switch( subChoice )
{
case 0:
{
SortTest sortTest(count, start, end);
sortTest.directInsertSort();
}
break;
case 1:
{
SortTest SortTest(count, start, end);
SortTest.shellSort();
}
break;
default:
break;
}
}
// 处理选择排序
void selectSortHandler(int count, int start, int end)
{
printSelectSort();
int subChoice = 0;
cin >> subChoice;
switch(subChoice)
{
case 0:
{
SortTest sortTest(count, start, end);
sortTest.simpleSelectSort();
}
break;
case 1:
{
SortTest sortTest(count, start, end);
sortTest.maxHeapSort();
}
break;
default:
break;
}
}
// 处理归并排序
void mergeSortHandler(int count, int start, int end)
{
SortTest sortTest(count, start, end);
sortTest.mergeSort();
}
// 处理基数排序
void baseDigitHandler(int count, int start, int end)
{
SortTest sortTest(count, start, end);
sortTest.baseDigitSort();
}
void main()
{
int randDigitCount = 10; // 随机数的个数
int randDigitStart = 0; // 随机数的最小值
int randDigitEnd = 100; // 随机数的最大值
while (1)
{
printMenu(randDigitCount, randDigitStart, randDigitEnd);
int choice = 0;
cin >> choice;
switch(choice)
{
case 0:
{
cout << "请输入随机数的数量:" << endl;
cin >> randDigitCount;
}
break;
case 1:
{
cout << "请输入随机数的最小和最大值,中间用空格隔开" << endl;
cin >> randDigitStart >> randDigitEnd;
}
break;
case 2:
{
swapSortHandler(randDigitCount, randDigitStart, randDigitEnd);
}
break;
case 3:
{
insertSortHandler(randDigitCount, randDigitStart, randDigitEnd);
}
case 4:
{
selectSortHandler(randDigitCount, randDigitStart, randDigitEnd);
}
break;
case 5:
{
mergeSortHandler(randDigitCount, randDigitStart, randDigitEnd);
}
break;
case 6:
{
baseDigitHandler(randDigitCount, randDigitStart, randDigitEnd);
}
default:
break;
}
}
}