一,使用排序对象测试排序;
建立一个头文件adt.h,加上头文件
建立一个Sort.h文件加入以下代码
#include"adt.h"
class Sort
{
public:
void keep(int a[],int b[]); //使数组始终保持无序的状态
void show(int a[]) //内联函数
{
for(int i = 0;i < 12;i++)
{
printf("%d ",a[i]);
}
printf("%d",a[12]);
}
void Q_Sort(int a[],int left,int right);
void Shell_sort(int a[],int n);
void Choose_sort(int a[],int n);
void mopao_sort(int a[],int n);
void ins_sort(int a[],int n);
void Merge_sort(int a[],int n);
void dui_sort(int a[],int n);
};
在cpp文件中加入
#include"adt.h"
#include"Sort.h"
//声明为内敛函数
inline void Swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
void Sort::keep(int a[],int b[])
{
for(int i = 0;i < 13;i++)
a[i] = b[i];
}
int Partition(int a[],int left,int right) //快排的主函int数体,排区间[left,right);不包括右端点
{
right--; //不包括右边界
int i,j;
int povite = a[right];
i = left;
j = right; //从枢轴开始,因为是等于
while(i != j)
{
while(a[i] <= povite && i < j)i++;
while(a[j] >= povite && i < j)j--;
if(i < j)
Swap(a[i],a[j]);
}
Swap(a[right],a[i]); //交换枢轴,最终使左边的比枢轴小,右边的比枢轴大
return i;
}
void Sort::Q_Sort(int a[],int left,int right)
{
Sort s;
if(right > left) //区间中最少有一个数字,因为不包括右边界所以不能等于
{
int p = Partition(a,left,right);
s.show(a);
printf("\n");
Q_Sort(a,left,p); //不包括枢轴
Q_Sort(a,p + 1,right);
}
}
void Sh_sort(int a[],int n,int d)
{
Sort s;
for(int i = d;i < n;i++) //从后向前进行查看
{
int j = i;
int temp = a[i];
while(j >= d && temp < a[j - d])
{
a[j] = a[j - d];
j -= d;
}
a[j] = temp;
}
}
void Sort::Shell_sort(int a[],int n)
{
Sort s;
int d = n;
while(d)
{
d = d / 2;
Sh_sort(a,n,d);
s.show(a);
printf("\n");
}
}
//选择排序
void Sort::Choose_sort(int a[],int n)
{
Sort s;
for(int i = 0;i < n - 1;i++)
{
int temp = a[i];
int t = i; //每循环一次记录最小的下标数下标
for(int j = i + 1;j < n;j++)
{
if(a[j] < a[i])
{
t = j;
a[i] = a[j];
}
}
if(i != t)
{
a[t] = temp;
}
s.show(a);
printf("\n");
}
}
//冒泡排序
void Sort::mopao_sort(int a[],int n)
{
Sort s;
for(int i = 0;i < n - 1;i++)
{
for(int j = i + 1;j < n;j++) //交换相邻的两个,如果前面的比后面的大的话
{
if(a[i] > a[j])
Swap(a[i],a[j]);
}
s.show(a);
printf("\n");
}
}
//插入排序
void Sort::ins_sort(int a[],int n)
{
Sort s;
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;
s.show(a);
printf("\n");
}
}
//归并排序
void mergea(int a[],int first,int mid,int last,int p[]) //合并数组[first,mid)和[mid,last)
{
int t = 0;
int i = first;
int j = mid;
while(i < mid && j < last)
{
if(a[i] < a[j]) //将小的一项加入数组
{
p[t++] = a[i++];
}
else
{
p[t++] = a[j++];
}
}
//合并后两个有剩余的将其剩余项加入临时数组
while(i < mid)
{
p[t++] = a[i++];
}
while(j < last)
{
p[t++] = a[j++];
}
for(int k = 0;k < t;k++)
{
a[first + k] = p[k]; //将数拷贝到元素组中
}
}
void mergesort(int a[],int first,int last,int temp[]) //分治
{
if(first + 1 < last) //里面有一个数不能进行分组了就
{
int mid = (first + last) / 2;
mergesort(a,first,mid,temp); //左边有序
mergesort(a,mid,last,temp); //右边有序
mergea(a,first,mid,last,temp); //合并
}
}
void Sort::Merge_sort(int a[],int n) //调用函数
{
int *p = new int[n];
if(p == NULL)
{
printf("没有空间了,删除点东西把\n");
}
mergesort(a,0,n,p);
delete[] p;
return ;
}
//堆排序
void AdjuHeap(int a[],int pos,int n) //调整堆调整的堆为[pos,n-1],或者说是[pos,n);
{
int tmp = a[pos];
int pos_mchild ;
//因为从下至上对根进行排序,所以子树已经排好了顺序,直接找到第一个比tmp小的,插入就可以了,相当于插入排序。
while(pos * 2 + 1 < n)
{
pos_mchild = pos * 2 + 1; //左孩子为2 * n + 1,右孩子为2 * n + 2;
if(a[pos_mchild] < a[pos_mchild + 1] && pos_mchild != n - 1) //找到左右孩子中较大的一个记录下标
pos_mchild++;
if(tmp < a[pos_mchild])
a[pos] = a[pos_mchild];
else
break;
pos = pos_mchild;
}
a[pos] = tmp;
}
//[n/2,n)为叶子节点;
void createHeap(int a[],int n) //创建大根堆
{
for(int i = n / 2 - 1;i >= 0;i--)
{
AdjuHeap(a,i,n);
}
}
void Sort::dui_sort(int a[],int n) //堆排序
{
createHeap(a,n);
for(int i = n - 1;i > 0;i--) //大根堆,第一个最大,应该是a[n - 1];
{
int tmp = a[i];
a[i] = a[0];
a[0] = tmp;
AdjuHeap(a,0,i);
}
}
主函数
#include"adt.h"
#include"Sort.h"
int main()
{
int a[] = {2,5,8,51,7,1,58,5,5,8,4,2,5};
int b[] = {2,5,8,51,7,1,58,5,5,8,4,2,5};
Sort s;
//快排测试
printf("快速排序\n");
s.Q_Sort(a,0,13);
printf("输出为:\n");
s.show(a);
printf("\n");
s.keep(a,b); //打乱a的顺序
//希尔排序
printf("希尔排序\n");
s.Shell_sort(a,13);
printf("输出为:\n");
s.show(a);
printf("\n");
s.keep(a,b);
//堆排序
printf("堆排序\n");
s.dui_sort(a,13);
printf("输出为:\n");
s.show(a);
printf("\n");
s.keep(a,b);
//归并排序
printf("归并排序\n");
s.Merge_sort(a,13);
printf("输出为:\n");
s.show(a);
printf("\n");
printf("完成\n");
s.keep(a,b);
//简单选择排序
printf("\n");
printf("简单选择排序\n");
s.Choose_sort(a,13);
printf("输出为:\n");
s.show(a);
printf("\n");
s.keep(a,b);
//冒泡排序
printf("\n");
printf("冒泡排序\n");
s.mopao_sort(a,13);
printf("输出为\n");
s.show(a);
printf("\n");
s.keep(a,b);
//简单插入排序
printf("\n");
printf("简单插入排序\n");
s.ins_sort(a,13);
printf("输出为\n");
s.show(a);
printf("\n\n");
printf("所有排序测试完成\n");
printf("按任意键继续\n");
getch();
return 0;
}
输出的结果是将每一遍的排序输出,将具体的细节展现出来方便学习
二.具体讲解
插入排序
插入排序的思想是将假设已经有一个有序的序列,将后面没有顺序的序列插入这个有序的序列之中。具体细节如下:
//插入排序
void ins_sort(int a[],int n)
{
Sort s;
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;
}
}