五、希尔排序
希尔排序我们需要借助变量gapk来实现(gap是变量名,k是下脚标),这个排序算法主要是通过比较相距gapk间隔的元素值的大小来进行排序,并且在一组数据当中,所有相距gapk的元素都被排序。
希尔排序的思路是:确定一个元素间隔gap,将参加排序的元素从第一个元素开始按照这个间隔依次分成多个子序列,分别将所有位置的相隔gap的元素看成一个子序列。例如对于一组数据{2,9,3,7,10,1,5,4,6,8}来说,我们以gap = 4来进行划分,则是如下这个样子的:
序列一:2 9 3 7 10 1 5 4 6 8 ——对2,和10进行排序
序列二:2 9 3 7 10 1 5 4 6 8——对9和1进行排序
序列三:2 9 3 7 10 1 5 4 6 8——对3和5进行排序
序列四:2 9 3 7 10 1 5 4 6 8——对7和4进行排序
序列五:2 9 3 7 10 1 5 4 6 8——对10和6进行排序
序列六:2 9 3 7 10 1 5 4 6 8——对1和8进行排序
在这个例子中,我们把数据划分成了六个子序列,对于每个子序列,我们可以采用其他排序算法,如冒泡排序、插入排序等,然后缩小gap的值,按照新的gap值划分数组,再分别对每个子序列排序……以此类推,直到gap值递减为1。
关于gap:目前较为流行的gap的选择方法是采用shell方法,即:每次gap值都减半。例如,还是以上面那组数据{2,9,3,7,10,1,5,4,6,8}为例:
初始状态:2 9 3 7 10 1 5 4 6 8
第一趟:gap = 4,排序结果:2 1 3 4 6 8 5 7 10 9
第二趟:gap = 2,排序结果:2 1 3 4 5 7 6 8 10 9
第三趟:gap = 1,排序结果:1 2 3 4 5 6 7 8 9 10
排序结束。
代码:
#include<iostream>
using namespace std;
void Swap(int* a,int* b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void shellSort(int a[],int n)
{
int i,j,flag,counter = 1;
int gap = n;
while(gap>1)
{
gap = gap/2; ///每次gap都减半。
do///子序列排序我们这里采用冒泡排序的方法。
{
flag = 0;
for(i=0;i<=n-gap-counter;i++)
{
j = i+gap;
if(a[i]>a[j])
{
Swap(&a[i],&a[j]);
flag = 1;
}
}
}while(counter<n&&flag==1);
}
}
六、选择排序
选择排序的思想是:重复的从待排序的元素中挑选出最大的或者最小的元素进行排序。我们选择从小到大的选择最大元素进行排序的方式进行讲解。
选择排序的基本思路是:第i趟排序从待排序的前n-i+1个元素里面选出最大的元素,并与这n-i+1个元素的最末位置的元素进行交换,知道i = n-1 。也就是说,选择排序最多进行n-1趟。
我们还以{2,9,3,7,10,1,5,4,6,8}举例,其中{}代表整个数据的集合,“()”代表已经排好的元素
初始状态:2 9 3 7 10 1 5 4 6 8
第一趟:所有元素中10最大,与最末位置的8进行交换,得到:2 9 3 7 8 5 4 6 1(10)
第二趟:剩余的元素中9最大,与最末位置的1进行交换,得到:2 1 3 7 8 5 4 6 (9 10)
第三趟:剩余的元素中8最大,与最末位置的6进行交换,得到:2 1 3 7 6 5 4 (8 9 10)
第四趟:剩余的元素中7最大,与最末位置的4进行交换,得到:2 1 3 4 6 5 (7 8 9 10)
……
以此类推
第九趟:排序完成得到:(1 2 3 4 5 6 7 8 9 10)
代码:
#include<iostream>
using namespace std;
void selectionSort(int a[],int n)
{
int i = 1;
int Max; ///用于记录每趟排序中最大的那个元素。
int temp;
while(i<n)
{
Max = n-i;///将Max初始化为待排元素最末位置
for(int j=0;j<n-i+1;j++)
{
if(a[j]>a[Max])
{
Max = j;
}
}
if(Max!=n-i) ///将最大元素与最末元素进行交换
{
temp = a[Max];
a[Max] = a[n-i];
a[n-i] = temp;
}
i++;
}
}