说在前面的废话:以前在学习数据结构排序那一章的时候就想,什么时候有空了,做一个排序比较器。比较这些排序的效果。最近刚好有空,就利用Qt的图形界面做了一个排序比较器。记录在此,方便自己,也希望有助于大家。
本文主要分以下几个部分叙述:
1、项目介绍
2、编写九大排序
3、在子线程中测试排序
4、等待框制作
5、结果
一、项目介绍
本程序是一个比较九大排序算法效率的演示程序。如下图所示:
用户可以通过选择数量规模,来选择需要测试的数量大小。数量规模数量级从10-1000000;本程序的原始数据随机生成的int型正整数数据,大小从0-1000000;还有,通过选择排序方式选择需要比较的排序算法,(可多选);选择是否记录结果,将决定程序是否把随机生成的原始数据和排序的数据记录到文件中。同时,在右边的结果显示框,还可以显示程序运行的进度和结果。
二、编写九大排序
对于排序来说,总共有很多很多很多种,这里选择了基础的九大排序。如下图所示:
具体的代码如下:
//简单插入排序
void Sort::SimInsSort() //1 4 3 2 7 9 5
{
int i,j,temp;
for( i = 1;i<num;++i)
{
temp = data[i]; //当前待比较的数
for( j = i-1;j>=0;--j)
{
if(temp<data[j])
data[j+1] = data[j]; //数据向后移动
else
break;
}
data[j+1] = temp; //插入
}
}
//希尔排序
void Sort::ShellSort() //1 4 3 2 7 9 5
{
int gap = 1; //间隔
while (gap < num / 3) // 动态定义间隔序列
{
gap = gap * 3 + 1;
}
int i,j,temp;
for(;gap>0;gap/=3)
{
for( i = gap;i<num;++i)
{
temp = data[i];
for(j = i-gap;j>=0;j-=gap)
{
if(temp<data[j])
data[gap+j] = data[j];
else
break;
}
data[j+gap] = temp;
}
}
}
//冒泡排序算法
void Sort::BubSort()
{
int flag = 0;
for(int i = 1;i<num;++i)
{
if(0 == flag)
{
flag = 1;
for(int j = 0;j<num-i;++j)
{
if(data[j]>data[j+1])
{
int temp = data[j];
data[j] = data[j+1];
data[j+1] = temp;
flag = 0;
}
}
}
}
}
//设定基准,并返回基准的位置 //6
int Sort::Partion(int low, int high) //1 3 3 7 10
{
//int piv = low;
int temp = data[low];
while(low<high)
{
while(low<high)
{
if(data[high]>=temp)
--high;
else
break;
}
data[low] = data[high];
while(low<high)
{
if(data[low]<=temp)
++low;
else
break;
}
data[high] = data[low];
}
data[low] = temp;
return low;
}
//堆化:建立以当前元素i为根节点的大根堆
void Sort::Heapify(int length,int i)
{
int left_chi = i*2+1,rig_chi = i*2+2;
int large = i;
if(left_chi<length && data[left_chi]>data[large])
large = left_chi;
if(rig_chi < length && data[rig_chi]>data[large])
large = rig_chi;
if(large != i)
{
//交换当前元素与其孩子的最大值
int t = data[i];
data[i] = data[large];
data[large] = t;
Heapify(length,large);
}
}
//初始化大根堆
void Sort::InitMaxHeap(int length)
{
for(int i = length/2-1;i>=0;--i)
Heapify(length,i);
}
//合并两个有序序列
void Sort::Merge(int beg, int mid, int end)
{
int i1 = beg,j1 = mid;
int i2 = mid+1,j2 = end; //i2,j2为第二个有序序列的首部和尾部
int *temp = new int[end-beg+1]; 此处需要在堆中申请内存,否则百万级的数据,程序会崩溃
int temp_index = 0;
while(i1<=j1 && i2<=j2)
{
if(data[i1]<data[i2])
{
temp[temp_index++] = data[i1];
++i1;
}
else if(data[i1]>data[i2])
{
temp[temp_index++] = data[i2];
++i2;
}
else
{
temp[temp_index++] = data[i1];
temp[temp_index++] = data[i2];
++i1;
++i2;
}
}
//将剩下的元素复制进排序好的暂时空间中
while(i1<=j1)
{
temp[temp_index++] = data[i1];
++i1;
}
while(i2<=j2)
{
temp[temp_index++] = data[i2];
++i2;
}
//复制回原数组
for(int i = beg,k = 0;i<=end;++i,++k)
{
data[i] = temp[k];
}
delete temp;
}
//二路归并排序
void Sort::MergeSort(int beg,int end)
{
if(beg<end)
{
int mid = (beg+end)/2;
MergeSort(beg,mid); //归并左半边
MergeSort(mid+1,end); //归并右半边
Merge(beg,mid,end); //左右合并
}
}
//计数排序
void Sort::CountSort()
{
int max = data[0],min = data[0];
//获取元素中的最小值和最大值
for(int i = 0;i<num;++i)
{
if(max<data[i])
max = data[i];
if(min>data[i])
min = data[i];
}
int dif = max-min; //最大值和最小值的差值
//int fre[dif+1]; // 频率数组
int *fre = new int[dif+1]; //此处需要在堆中申请内存,否则百万级的数据,程序会崩溃
for(int i = 0;i<dif+1;++i)
fre[i] = 0; //初始化为零
for(int i = 0;i<num;++i)
{
++fre[data[i]-min]; //统计每个数的频率
}
//输出到原数组
for(int i = 0,j = 0;i<num;++i)
{
while(fre[j] <= 0) ++j;
data[i] = j+min;
--fre[j];
}
delete fre;
}
//分发和收集
void Sort::DisAndCol(int exp)
{
int bucs[10];
for(int i = 0;i<10;++i)
bucs[i] = 0;
//统计频率
for(int i = 0;i<num;++i)
{
int d = (data[i] / exp) %10;
++bucs[d];
}
//统计在本次分发之后收集的位置
for(int i = 1;i<10;++i)
{
bucs[i] = bucs[i-1]+bucs[i];
}
//int temp[num];
int *temp = new int[num]; //此处需要在堆中申请内存,否则十万以上的数据,程序会崩溃
for(int i = 0;i<num;++i) temp[i] = data[i];
for(int i = num-1;i>=0;--i)
{
int d = (temp[i]/exp)%10; //取得单个位数
data[bucs[d]-1] = temp[i]; //复制回原数组
--bucs[d]; //减去一个计数
}
delete temp;
}
//基数排序
void Sort::RadSort()
{
//int b = 6; 6代表数字的位数,此处默认最大是6位,即100000
int b = 7; 7代表数字的位数,此处默认最大是7位,即1000000
for(int i = 0;i<b;++i)
{
int exp = pow(10,i);
DisAndCol(exp);
}
}
//快速排序
void Sort::QuiSort(int low,int high)
{
if(low<high)
{
int par_index = Partion(low,high);
QuiSort(low,par_index-1);
QuiSort(par_index+1,high);
}
}
//堆排序
void Sort::HeapSort()
{
int length = num;
InitMaxHeap(length); //初始化大根堆
for(int i = 0;i<num-1;++i)
{
//交换堆头元素和堆尾元素
int t = data[0];
data[0] = data[num-i-1];
data[num-i-1] = t;
--length;
Heapify(length,0); //每次交换后都从头部开始往下调整,调整的元素数目减一
}
}
//简单选择排序
void Sort::SimSelSort()
{
int i,j,min_index;
for( i = 0;i<num;++i)
{
min_index = i;
for(j = i;j<num;++j)
{
if(data[min_index] > data[j]) //选择最小数的下标
min_index = j;
}
if(min_index != i)
{
int t = data[min_index];
data[min_index] = data[i];
data[i] = t;
}
}
}
具体各排序原理在网上书上都有很多介绍,在此就不赘述了。
总共内容比较多,在这先写这些,剩下的见排序比较器(下)