#include "main.h"
#include<iostream>
#include<string>
using namespace std;
void merge(int a[], int L, int M, int R);
void printNum(int arr[], int len, string flag)
{
cout <<"********" << flag <<"*******" << endl;
for (int i = 0; i < len; i++)
cout << arr[i]<<" ";
cout << endl;
cout << "*************************" << endl;
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
/****冒泡排序实现*************
1.外层i循环n-1次,这是控制循环次数的。
2.内层j,j对应的实际下标,循环n-i-1次,
-i是因为每次循环完后最后一位就排好序了,对应为n-i次。
-1是因为要取到j+1的值。
******************************/
void bubbleSort(int a[], int len) {
for (int i = 0; i < len - 1; i++)
{
int flag = 0;
for (int j = 0; j < len - i - 1; j++)
{
if (a[j] > a[j + 1])
{
flag = 1;
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
if (flag == 0)
break;
}
}
/*选择排序实现
1.外层i循环n-1次,这是控制循环次数的。
2.内层j,j对应的实际下标,循环n-i次,
-i是因为每次循环完后最后一位就排好序了,对应为n-i次。
******************************/
void selectSort(int a[], int len) {
for (int i = 0; i < len - 1; i++)
{
int maxtmp = 0;
for (int j = 0; j < len - i ; j++)
{
if (a[j] > a[maxtmp])
{
maxtmp = j;
}
}
swap(a[maxtmp],a[len-i-1]);
}
}
/*插入排序*
1.外层i循环n-1次,这是由于每次排序相当于把一个数插入一个已排好序的数组,所以下标从1到结束。
2.将已排好序的数组从后往前依次与要插入的数比较,当比要插入的数大时就往后移位。
********************************/
void insertSort(int a[], int len)
{
for (int j = 1; j < len; j++)
{
int tmp = a[j];
int k = j;
while (k > 0 && tmp < a[k - 1])
{
a[k] = a[k-1];
k--;
}
a[k] = tmp;
}
}
/**快排的思想是找到中间值,
然后左边从左往右找到比中间值大的值
然后右边从右往左找比中间值小的值
交换左右两边的值
取左边界到右边找到值的区间再次递归调用
取左边找到值到右边界的区间再次递归调用*/
void quicksort(int a[], int L, int R)
{
int i = L;
int j = R;
int mout = a[L / 2 + R / 2];
while (i <= j) {
while (mout > a[i]) {
i++;
}
while (mout < a[j]) {
j--;
}
if (i <= j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
i++;
j--;
}
}
if (L < j) {
quicksort(a,L,j);
}
if (i < R) {
quicksort(a, i, R);
}
}
/**
归并排序:开始于将两个有序数组合并成一个
当然数据不可能是有序的,所以在归并时使用递归将数组划分,然后每轮递归
**/
void mergsort(int a[],int L,int R)
{
if(L==R)
{
return;
}
else
{
int mid = (L / 2 + R / 2);
mergsort(a,L,mid);
mergsort(a,mid+1,R);
merge(a,L,mid+1,R);
}
}
void merge(int a[], int L, int M, int R)
{
int* lifta = new int[M-L];
int* righta = new int[R-M+1];
for (int i = L; i < M; i++)
{
lifta[i-L] = a[i];
}
for (int i = M; i <= R; i++)
{
righta[i - M] = a[i];
}
int i = 0;
int j = 0;
int k = L;
while (i < (M - L) && j < (R - M + 1))
{
if (lifta[i] < righta[j])
{
a[k++] = lifta[i++];
}
else
{
a[k++] = righta[j++];
}
}
while (i < (M - L))
{
a[k++] = lifta[i++];
}
while (j < (R - M + 1))
{
a[k++] = righta[j++];
}
delete lifta, righta;
}
/**希尔排序
插入排序的一种形式采用的是元素间下标隔断递增的形式进行插入操作
**/
void shellsort(int a[], int len)
{
for (int step = len / 2; step > 0; step /= 2)
{
for (int i = step; i < len; i++)
{
int j = i;
int tmp = a[j];
while (j >= step && a[j - step] > tmp)
{
a[j] = a[j - step];
j -= step;
}
a[j] = tmp;
}
}
}
/****堆排序 先说清楚,完全没看明白 一度对自己的智商产生了怀疑 于是决定先把代码敲了****/
void adjust(int a[], int idx1, int idx2)
{
if (nullptr == a || idx1 >= idx2 || idx1 < 0 || idx2 < 0)
return;
int tmp = a[idx1];//存放暂时要调整的数据
for (int idx = idx1 * 2 + 1; idx <= idx2; idx = idx * 2 + 1)//从要调整的数据的左孩子开始比较
{
//选出左右孩子中的最大节点
if(idx + 1 <= idx2 && a[idx] < a[idx + 1])
++idx;
if (a[idx] > tmp)
{
a[idx1] = a[idx];
idx1 = idx;
}
else
{
break;
}
}
a[idx1] = tmp;
}
void headSort(int a[], int len)
{
if (nullptr == a || len <= 0)
return;
//数组中顺序存放的数据对应完全二叉树堆中的对应节点的值,现在调整为大根堆
for (int i = len / 2 - 1; i >= 0; i--)//由于堆结构构造的特殊性,(len/2-1就是表示最后一个非叶子节点)从最后一个非叶子节点调整为最大堆
{
adjust(a,i,len-1);//最后一个非叶子节点和它的孩子比较调整
}
//排序,根节点和最后一个节点交换,调整
for (int i = len - 1; i > 0; --i)
{
swap(a[0],a[i]);//每次选出一个最大的数放到末尾,也就是数组末尾
adjust(a,0,i-1);
}
return ;
}
//测试
int main(void) {
int girl[] = { 21,32,17,33,20,34,28,27,1 };
int len = sizeof(girl) / sizeof(girl[0]);
printNum(girl, len, "排序前");
headSort(girl, len);
printNum(girl, len, "排序后");
system("pause");
return 0;
}