#include<iostream>
using namespace std;
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
void print(int a[], int n)
{
printf("\n");
for (int i = 0; i < n; i++)
{
printf(" %d ", a[i]);
}
}
//冒泡排序
void bubblesort(int a[], int n)
{
for (int i = n - 1; 0 < i; i--)
{
for (int j = 0; j <i; j++)
{
if (a[j]>a[j + 1])
{
swap(a[j], a[j + 1]);
}
}
}
}
//插入排序
void insertsort(int a[], int n)
{
for (int i = 1; i < n; i++)
{
int temp = a[i];
int j = i;
while ((temp < a[j - 1]) && j>0)
{
a[j] = a[j - 1];//右移
j--;
}
a[j] = temp;
}
}
void shell_sort1(int a[], int n)//希尔排序--也称为分组插入排序!!!!
{
int i, j, gap;
// gap为步长,每次减为原来的一半。
for (gap = n / 2; gap > 0; gap /= 2)//回合
{
// 共gap个组,对每一组都执行直接插入排序
for (i = 0; i < gap; i++)///组数
{
for (j = i + gap; j < n; j += gap)//相当于 for (int i = 1; i < n; i++)
{
// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
int tmp = a[j];
while (j >= 0 && a[j-gap] > tmp)// while ((temp < a[j - 1]) && j>0)
{
a[j] = a[j-gap];
j-= gap;
}
a[j] = tmp;
}
}
}
}
//快速排序
void quicksort(int a[], int lo, int hi)
{
int base = a[lo];
int i = lo;
int j = hi;
while (i <= j)
{
while (base > a[i]) i++;
while (base < a[j]) j--;
if (i <= j)//没有等号就出不来了
{
swap(a[i], a[j]);
i++;
j--;
}
}
if (lo < j) quicksort(a, lo, j);
if (i < hi) quicksort(a, i, hi);
}
//归并排序
void Merge(int array[], int left, int mid, int right)// 归并排序中的合并算法
{
int aux[20] = { 0 }; // 临时数组 (若不使用临时数组,将两个有序数组合并为一个有序数组比较麻烦)
int i=left; //第一个数组索引
int j = mid + 1; //第二个数组索引
int k; //临时数组索引
for ( k = 0; k <= right - left; k++) // 分别将 i, j, k 指向各自数组的首部。
{
//若 i 到达第一个数组的尾部,将第二个数组余下元素复制到 临时数组中
if (i == m + 1)
{
aux[k] = array[j++];
continue;
}
//若 j 到达第二个数组的尾部,将第一个数组余下元素复制到 临时数组中
if (j == right + 1)
{
aux[k] = array[i++];
continue;
}
//如果第一个数组的当前元素 比 第二个数组的当前元素小,将 第一个数组的当前元素复制到 临时数组中
if (array[i] < array[j])
{
aux[k] = array[i++];
}
//如果第二个数组的当前元素 比 第一个数组的当前元素小,将 第二个数组的当前元素复制到 临时数组中
else
{
aux[k] = array[j++];
}
}
//i = left , 被排序的数组array 的起始位置
//j = 0, 临时数组的起始位置
for (i = left, j = 0; i <= right; i++, j++)
{
array[i] = aux[j];//将有序的临时数组 元素 刷回 被排序的数组 array 中,
}
}
void MergeSort(int array[], int lo, int hi)
{
if (lo < hi)//终止条件了
{
int mid = (lo + hi) / 2;
// 对前半部分进行排序 ---------------------先是无限切分,,,,再从底部往上归并
MergeSort(array, lo, mid);
// 对后半部分进行排序
MergeSort(array, mid + 1, hi);
// 合并前后两部分
Merge(array, lo, mid, hi);
}
}
//堆排序
void HeapAdjust(int a[], int m, int n)//构造大根堆(让a[m]到a[n]满足大根堆)
{
int max;
int lc;//左孩子
int rc;//右孩子
while (1)//weile 循环
{
//获取a[m]的左右孩子
lc = 2 * m + 1;
rc = 2 * m + 2;
//比较a[m]的左右孩子,max记录较大者的下标
if (lc >= n)//终止条件
{
break;//不存在左孩子则跳出
}
if (rc >= n)
{
max = lc;//不存在右孩子则最大孩子为左孩子
}
else
{
max = a[lc] > a[rc] ? lc : rc;//左右孩子都存在则找出最大孩子的下标
}
//判断并调整(交换)
if (a[m] >= a[max])//父亲比左右孩子都大,不需要调整,直接跳出
{
break;
}
else
{//否则把小父亲往下换
swap(a[m], a[max]);
m = max; //准备下一次循环,注意力移动到孩子身上,因为交换之后以孩子为根的子树可能不满足大根堆
}
}
}
void HeapSort(int a[], int n)
{
int i, j;
for (i = n / 2 - 1; i >= 0; i--)//自下而上构造大根堆(初始堆)
{//a[n/2 - 1]恰好是最后一个非叶子节点(叶子节点已经满足小根堆,只需要调整所有的非叶子节点),一点小小的优化
HeapAdjust(a, i, n);
}
for (i = n - 1; i > 0; i--)
{
swap(a[i], a[0]);//首尾交换,断掉尾巴
HeapAdjust(a, 0, i);//断尾后的部分重新调整 一直i--,,从下标0开始重新建堆到i
}
}
//选择排序
void selectsort(int a[], int n)
{
for (int i = 0; i < n - 1; i++)
{
int k = i;
for (int j = i + 1; j < n; j++)
{
if (a[j] < a[i])
{
k = j;
}
}
swap(a[k], a[i]);
}
}
//基数排序
void main()
{
//int a[5] = { 2, 4, 1, 3, 0 };
int a[20] = { 0, 1, 17, 3, 4, 5, 13, 18, 11, 9, 10, 8, 12, 6, 14, 15, 16, 2, 7, 19 };
printf("排序前:\n");
print(a, 20);
//bubblesort(a, 5);
//insertsort(a, 20);
shell_sort1(a, 20);
//quicksort(a, 0, 19);
//selectsort(a, 5);
//HeapSort(a, 5);
//MergeSort(a, 0, 4);
//shellSort(a,20);
printf("\n排序后:\n");
print(a, 20);
getchar();
}
冒泡排序,插入排序,快速排序,归并排序,堆排序,选择排序,希尔排序
最新推荐文章于 2023-01-19 08:30:00 发布