#include <windows.h>
#include<iostream>
#include <time.h>
using namespace std;
//分割数组为两部分,一部分大于temp,一部分小于temp
int partion(int* arr, int begin, int end)
{
int i = begin;//记录开头
int j = end;//记录结尾
int temp = arr[begin];//记录某个值,用来分割数组,一般取数组开头的值
while (i < j)//循环条件为前段下标大于后段下标,数组还未遍历完
{
while (arr[j] >= temp && i < j)//一直循环,直到找到小于temp的数
j--;//循环时j前移
arr[i] = arr[j];//找到了小于temp的数,将它赋值给前面的arr[i]
while (arr[i] < temp && i < j)//一直循环,直到找到大于temp的数
i++;//循环时i后移
arr[j] = arr[i];//找到了大于temp的数,将它赋值给前面的arr[j]
}//循环结束
arr[i] = temp;//此时i=j,把temp存入
return i;//此时的i即为分界点,一部分大于temp,一部分小于temp
}
//快速排序算法(从小到大)
//arr:需要排序的数组,begin:需要排序的区间左边界,end:需要排序的区间的右边界
void quickSort(int* arr, int begin, int end)
{
if (begin >= end)//递归终止条件
return;
int mid = partion(arr, begin, end);//记录分割点下标
quickSort(arr, begin, mid - 1);//递归前半部分
quickSort(arr, mid + 1, end);//递归后半部分
}
//选择排序:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,
//然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾
void selectSort(int *arr,int n)
{
int minIndex = 0;//初始化最小值索引为0
int min = 0;//初始化最小值为0
for (int i = 0; i < n; i++)//遍历元素
{
minIndex = i;//暂存索引
min = arr[minIndex];//暂存值
for (int j = i + 1; j < n; j++)//从i+1向后遍历
{
if (arr[j] < min)//如果小于暂存值
{
minIndex = j;//更新最小值索引
min = arr[minIndex];//更新最小值
}
}
if (minIndex != i)//如果找到比arr[i]小的值
{//交换两者的值
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
//插入排序:每次将一个待排序的元素与已排序的元素进行逐一比较,直到找到合适的位置按大小插入
//开始时,有序序列只有一个元素就即第一个元素
void insertSort(int *arr,int n)
{
for (int i = 0; i < n; i++)
{
int insertVal = arr[i];//暂存待插入值
int index = i - 1;//为什么不是int index = i?因为insertVal要跟它的前一个数比较
//如果非要写int index = i也可以,但是要修改后面的代码逻辑
while (index >= 0 && arr[index] > insertVal)
{//当遍历到的值比待插入值大时
arr[index + 1] = arr[index];//该值往后移
index--;//往前遍历
}//遍历到比待插入值小的元素
arr[index + 1] = insertVal;//在该元素(比待插入值小的元素)后方插入insertVal
}
}
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR] 闭区间
int* generateRandomArray(int n, int rangeL, int rangeR) {
//assert(rangeL <= rangeR);
int* arr = new int[n]; // 创建一个 n个元素的数组
srand(time(NULL)); // 随机种子
for (int i = 0; i < n; i++)
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
return arr;
}
//归并排序part2
void merge(int* arr, int left, int mid, int right)
{
int* temp = new int[right - left + 1];//新建暂存数组
int i = left;//记录左数组开始下标
int j = mid + 1;//记录右数组开始下标
int k = 0;//记录暂存数组索引值
while (i <= mid && j <= right)//当两个数组都没遍历完
{
if (arr[i] < arr[j])//取较小值存入temp
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
}
while (i <= mid)//如果还剩左数组没遍历完
temp[k++] = arr[i++];//直接放入temp
while (j <= right)//如果还剩右数组没遍历完
temp[k++] = arr[j++];//直接放入temp
k = 0;
//将temp中的元素全部拷贝到原数组中
while (left <= right)
{
arr[left++] = temp[k++];
}
delete[] temp;//删除暂存数组temp
}
//归并排序:利用归并思想将两个的有序数列合并成一个有序数列
void mergeSort(int* arr, int left, int right)
{
if (left >= right)//没有等号会栈溢出
return;
int mid = left + ((right - left) >> 1);//记录数组中间值
mergeSort(arr, left, mid);//递归左子数组
mergeSort(arr, mid + 1, right);//递归右子数组
merge(arr, left, mid, right);//按顺序合并数组
}
//希尔排序:直接插入排序算法的一种更高效的改进版本
void shellSort(int* arr, int n)
{
for (int gap = n / 2; gap > 0; gap /= 2)
{//初始化间隔为数组长度一半,步长为当前间隔的一半
for (int i = gap; i < n; i++)
{//初始化i为某一组元素的第二个
int temp = arr[i];//记录当前元素
int j = i - gap;//记录某一组元素的第一个
while (j >= 0 && arr[j] > temp)//当同组前面的值比后面值大时
{
arr[j + gap] = arr[j];//同组元素后移
j -= gap;//j往前遍历
}//遍历完成
arr[j + gap] = temp;//将暂存值放入arr[j + gap]
//注意不是arr[j],因为是当前元素跟前一个元素比,
//当前一个元素(arr[j])不满足要求时,将当前值放入arr[j]同组元素的后面
/*for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
arr[j + gap] = arr[j];
arr[j + gap] = temp;*/
}
}
}
int main()
{
SetConsoleOutputCP(CP_UTF8);//防止中文乱码
clock_t start, finish;
//int n = 8000000;
//int *num= generateRandomArray(n,0,999);
int n = 8;
int num[] = { 0, 1, 2, 4, 2, 2, 3, 1, 4 };
start = clock();//记录开始时间
//selectSort(num,n);
quickSort(num, 0, n - 1);
//mergeSort(num, 0, n - 1);
//insertSort(num,n);
//shellSort(num, n);
finish = clock();//记录结束时间
cout << "time:" << (double)(finish - start) / CLOCKS_PER_SEC << endl;
cout << "排序后的数组为:" << endl;
for (int i = 0; i < n; i++)
cout << num[i] << ' ';
cout << endl;
//delete[] num;
system("pause");
return 0;
}