排序那点事

排序
1.1经典的冒泡
冒泡算法:
1.比较前后两个数据,如果后面数据大于前面数据,则交换两者的位置,直到遍历完数组第0~N-1个数据后,最大的数据被”沉”到底下(第N-1号)
2.取N=N-1,如果N>0则继续比较;如果N=0,则结束比较
void BubbleSort(int a[], int n)
{
int i, j;
for(i = 0; i < n; i++)
for(j = 1; j < n; j++)
if(a[j-1] > a[j])
swap(a[j-1], a[j]);
}
 
冒泡演示
3 7 6 2 5 10 9 0
3 7//第一步,3和7比较,3<7,这两个数位置不变
   6 7//第二步,7和6比较,7>6,交换位置
        2 7//第三步,7和2比较,7>2,交换位置
         5 7//第四步,7和5比较,7>5,交换位置
            7 10//第五步,7和10比较,7<10位置不变
                              9 10//第六步,10和9比较,10>9,交换位置
                                 0 10//第七步,10和0比较,10>0,交换位置            //第一次循环结束,最大数10被”沉”在了最后一位
//继续循环…
 
1.2直接插入排序
将第i个数据插入前i个数据使得前i个数据有序
void Insertsort(int a[], int n)
{
int i, j, k;
for(i = 1; i < n; i++)
{//为a[i]在前面的i个数据中找到合适位置
for(j = i - 1; j >= 0; j--)
if(a[j] < a[i])
break;
//如果找到了这个位置
if(j != i-1)
{
//把比a[i]大的数据向后移
int temp = a[i];
for(k = i - 1; k > j; k--)
a[k+1] = a[k];
//放置a[i]
a[k+1]=temp;
}
}
}
直接 插入算法演示
3 7 6 2 5 10 9 0
3 7//第一步,把7插入前两个数据,使得前两个数据有序
3 6 7//第二步,把6插入前三个数据,使得前三个数据有序
  2 3 6 7//第三步,…
2 3 5 6 7//第四步,…
2 3 5 6 7 9//第五步,…
2 3 5 6 7 9 10//第六步,…
0 2 3 5 6 7 9 10//第七步,…
            //第一次循环结束,前两个数据排序完成
            //继续循环…
1.3直接选择排序
选择排序和插入排序类似,都是将数据分为有序区和无序区,差别是插入排序是将无序区的第一个数据插入到有序区从而形成一个更大的有序区而选择排序是从无序区中选择最小的数据插入到无序区的开头
void Selectsort(int a[], int n)
{
int i, j, max_index;
for(i = 0; i < n; i++)
{
max_index = i;//找最小元素的位置
for(j = i+1; j < n; j++)
if(a[j] < a[max_index])
max_index = j;
swap(a[i], a[max_index]);// 将这个元素放在无序区的开头
}
}
直接 选择算法演示
3 7 6 2 5 10 9 0
0//第一步,无序区为a[0]~a[7],在这8个数据中选出最小的数据0放在当前无序区a[0]~a[7]的开头
0 2//第二步,无序区为a[1]~a[7],在这7个数据中选出最小的2放在当前无序区a[1]~a[7],的开头
  0 2 3//第三步,…
0 2 3 5 //第四步,…
0 2 3 5 6//第五步,…
0 2 3 5 6 7 9//第六步,…
0 2 3 5 6 7 9 10//第七步,…
            //第一次循环结束,所有数据中最小的数据被放在第一位
            //继续循环…
1.4希尔排序
希尔排序的实质就是分组插入排序:先将整个序列分割成若干个子序列,分别进行直接插入排序,然后依次缩小增量再进行排序,待整个序列中的元素基本有序时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高
void shellsort(int a[], int n)
{
int j, gap;
for(gap = n / 2; gap > 0; gap /= 2)
for(j = gap; j < n; j++)
if(a[j] < a[j - gap])
{
int temp = a[j];
int k = j - gap;
while(k >= 0 && a[k] > temp)
{
a[k+gap] = a[k];
k -= gap;
}
a[k+gap]=temp;
}
}
希尔排序 算法演示
3 7 6 2 5 10 9 0
第一次循环n=7,gap=n/2=3,j=gap=3,
比较a[3]和a[0],a[3]<a[0],则进行直接插入排序,使得a[3]=3,a[0]=2
j++,j=4,比较a[4]和a[1],a[4]<a[1],则a[4]=7,a[1]=5
j++,j=5,比较a[5]和a[2],a[5]>a[2],不做改变
j++,j=6,比较a[6]和a[3],a[6]>a[3],不做改变
j++,j=7,比较a[7]和a[4],a[7]<a[4],则
temp=a[7]=0,k=4,a[4]>temp,所以a[7]=a[4]=7,k=k-gap=1,a[1]>temp,所以a[4]=a[1]=5,a[1]=0
一次循环之后,相隔为3的数据被排好序(a[0]<a[3]<a[6],a[1]<a[4]<a[7],a[2]<a[5])
继续循环…

1.5快排
快排,先定义三个数据low、high、val,分别表示需要排序的数据范围和一个标记,一次循环之后这个标记所指的数据会到排序完成的位置
举个例子就很明白了:
快排算法演示
3 7 6 2 5 10 9 0  //将数组a中所有数据排序
low=0,high=7,val=a[0]=3
则有a[low]=3,a[high]=0
当low<high时执行: 当low<high且a[high] >= val时,high--(升序排序,当第high位的数据大于val时满足目的,即升序,所以high继续指向下一个) ;当low<high且a[low]<val时,low++,原因和前面一样.最后会发现high=low,而此时的high(或low)就是val最后所在的位置
           
演示一次循环,
3 7 6 2 5 10 9 0
low=0, high=7,val=3;//初始a[low]=3,a[high]=0
因为val定义为a[low],所以开始从右边比较,val>a[high],所以,high不变=7,a[low]=a[high]=0,此时a[low]还是小于val,所以low++,low=1,此时循环条件不满足,a[high]=a[low]=7,继续从右边比较,a[high]>val,满足条件,high--,high=6,此时a[high]>val,high--,high=5,此时a[high]>val,high--,high=4,此时a[high]>val,high--,high=3,a[high]<val退出该层循环,a[low]=a[high]=2,a[low]<val,low++,low=2,此时a[low]>val退出该层循环,a[high]=a[low]=6;a[high]>val,high--,high=2.此时,low=high,这个low或high就是val最后所在的位置
接着再继续在val左右的两个无序数列中排序
 
int Findpos(int *a, int low, int high)
{
int val = a[low];
while(low < high)
{
while(low < high && a[high] >= val)
--high;
a[low] = a[high];
while(low < high && a[low] <= val)
++low;
a[high] = a[low];
}
a[low] = val;
return high;
}
void Quicksort(int *a, int low, int high)
{
int pos;
if(low < high)
{
pos = Findpos(a, low, high);
Quicksort(a, low, pos-1);
Quicksort(a, pos+1, high);
}
}
 
1.6 sort排序
Sort函数是STL里的,时间复杂度为n*log2(n)
使用这个函数,需要包含头文件#include <algorithm>
这个函数可以传两个参数或三个参数。第一个参数是要排序的区间首地址,第二个参数是区间尾地址的下一地址。也就是说,排序的区间是 [a,b) 。简单来说需要对数组 t 的第 0 到 len-1 的元素排序,就写 sort(t,t+len);
排序的数据类型不局限于整数,只要是定义了小于运算的类型都可以,比如字符串类 string 。
如果是没有定义小于运算的数据类型,或者想改变排序的顺序,就要用到第三参数——比较函数。
比较函数是一个自己定义的函数,返回值是 bool 型,它规定了什么样的关系才是“小于”。想把刚才的整数数组按降序排列,可以先定义一个比较函数 cmp
bool cmp(int a,int b)
{
return a>b;
}
排序的时候就写 sort(a,a+100,cmp);
关于sort的技巧还有很多,大家可以到网上查查

你可能感兴趣的:(排序算法总结)