排序

1、基本概念

  1、稳定排序:a == b,a本来在b前面,排序结束a仍然在b前面

  2、非稳定排序:a==b,a原本在b前面,排序结束b在a前面

  3、原地排序:排序过程中不申请新的空间

  4、非原地排序:需要利用额外的数组来辅助排序

  5、外部排序:排序的数据很大,不能一次容纳全部的排序记录,在排序过程中还需要访问外部存储器的排序

  6、内部排序:待排序数据记录完全存放在内存中所进行的排序过程,适合不太大的元素序列。

2、排序算法

  1、选择排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Selectsort(int a[],int n)
{
    int i;
    int j;
    int k;
    int min;
    int temp;
    for(i = 0;i < n;i++)
    {
        min = i;
        for(j = i + 1;j < n;j++)
        {
            if(a[min] > a[j])
            {
                min = j;
            }
        }
        if(i != min)
        {
            temp = a[i];
            a[i] = a[min];
            a[min] = temp;
        }
    }
}
//时间复杂度:O(n的平方)
//空间复杂度:O(1)
//非稳定排序
//原地排序

  2、插入排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void Insertsort(int a[],int n)
{
    int i;
    int j;
    int temp;
    int k;
    if(a == NULL || n < 2)
    {
        return ;
    }
    for(i = 0;i < n;i++)
    {
        temp = a[i];
        k = i-1;//挨个往前找
        //找到插入位置
        while(k >= 0 && a[k] > temp)
        {
            k--;
        }
        //腾出位置插进去,要插的位置是k+1;
        for(j = i;j > k+1; j--)
        {
            a[j] = a[j-1];
        }
        a[k+1] = temp;
    }
}
//时间复杂度O(n的平方)
//空间复杂度:O(1)
//稳定排序
//原地排序

  3、冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void Bubblesort(int a[],int n)
{
    int i;
    int j;
    int temp;
    for(i = 0;i < n;i++)
    {
        for(j = 0;j < n-i-1;j++)
        {
            if(a[j+1] < a[j])
            {
                temp = a[j+1];
                a[j+1] = a[j];
                a[j] = temp;
            }
        }
    }
}
//时间复杂度O(n的平方)
//空间复杂度O(1)
//稳定排序
//原地排序
 
//优化,如果一次循环下来一次交换操作都没有,说明此时数组有序
void highBubblesort(int a[],int n)
{
    int i;
    int j;
    int temp;
    int flag = 1;
    for(i = 0;i < n;i++)
    {
        for(j = 0;j < n-i-1;j++)
        {
            if(a[j+1] < a[j])
            {
                flag = 0;
                temp = a[j+1];
                a[j+1] = a[j];
                a[j] = temp;
            }
        }
        if(flag)
        {
            break;
        }
    }
}

  4、希尔排序

  希尔排序是插入排序的一种变种,无论是插入排序还是冒泡排序,如果数组的最大值刚好在第一位,需要将他挪到正确的位置就需要n-1次移动,也就是说,原数组的一个元素如果距离它正确的位置很远的话,则需要与相邻元素交换很多次才能到达正确的位置,这样相比比较花时间。

  希尔排序就是加快速度简单的改进了插入排序,交换不相邻的元素以对数组的局部进行排序。

  希尔排序的思想是采用插入排序的方法,先让数组中任意间隔为h的元素有序,刚开始h的大小可以是h = n/2,接着h = n/2,让h一直缩小,当h = 1时,也就是数组中任意间隔1的元素有序,此时的数组就是有序的了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//希尔排序(插入排序的变种)
//没有特别理解插入,所以代码写的不好
 
void sort(int a[],int n)
{
    int h;
    int i;
    int j;
    int temp;
    //遍历所有的步长
    for(h = n/2; h > 0;h /= 2)
    {
        //遍历所有的元素
        for(i = h;i < n;i++)
        {
            //遍历本组中的所有元素
            for(j = i-h; j >= 0;j-=h)//这个地方没太用到插入,可以用插入,但是写的那个插入不太对。
            {
                //如果当前元素大于加上步长后的元素
                if(a[j] > a[j+h])//
                {//有插入部分,非交换部分<br>void sort1(int a[],int n)
{
    int h;
    int i;
    int j;
    int current;
    //遍历所有的步长
    for(h = n/2; h > 0;h /= 2)
    {
        //遍历所有的元素
        for(i = h;i < n;i++)
        {
            j = i;
            current = a[i];
            while(j - h >= 0 && current < a[j - h])
            {
                a[j] = a[j-h];
                j = j-h;
            }
            a[j] = current;
        }
    }
}

  5、归并排序

  归并排序是建立在归并操作上的一种有效的排序算法,使用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列。即使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并

  把长度为n的输入序列分为长度为n/2的子序列;对着两个子序列分别采用归并排序;将两个排序号的子序列合并成一个最终的排序序列。

 

  6、快速排序

  基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字比另一部分的关键字小,则可对这两部分记录继续进行排序,以达到整个序列有序

  算法描述:快速排序使用分治法来把一个串分成两个串。

    从数列中调出一个数,称为基准(prvot)

    重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准后面(相同的数可以放在任一边),在这份分区退出后,该基准就处于数列的中间位置,这个称为分区操作。

    递归的把小于基准值元素的子数列和大于基准值元素的子数列排序。

   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void swap(int *x,int *y)
{
    int t;
    t = *x;
    *x = *y;
    *y = t;
}
 
void fastsort(int arr[],int start,int end)
{
    if(start >= end)
    {
        return ;
    }
    int mid = arr[end];
    int left = start;
    int right = end -1;
    while(left < right)
    {
        while(arr[left] < mid && left < right)
        {
            left++;
        }
        while(arr[right] >= mid && left < right)
        {
            right--;
        }
        swap(&arr[left],&arr[right]);
    }
    if(arr[left] >= arr[end])
    {
        swap(&arr[left],&arr[end]);
    }
    else
    {
        left++;
    }
    if(left)
    {
        sort(arr,start,left-1);
        sort(arr,left+1,end);
    }
}

  

  7、堆排序

  基本思想:利用堆这种数据结构设计的一种算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质,即子节点的键值或索引总是小于或大于它的父节点

  算法描述

  1、将待排排序关键字序列(R1,R2……Rn)构成大顶堆,此堆为初始的无序区

  2、将堆顶元素R【1】与最后一个元素R【n】交换,此时得到新的无序区(R1,R2……Rn-1)以及新的有序区(Rn),且满足R1,R2Rn-1<=R【n】

  3、由于交换后新的堆顶R【1】可能违反堆的性质,因此需要对当前无序区(R1,R2,Rn-1)调整为新堆,然后在将R【1】和无序区最后一个元素交换,得到新的无序区(R1,R2……Rn-2)和新的有序区(Rn-1,Rn),不断重复此过程直到有序区的元素个数为n-1,排序完成。   

 

  8、计数排序

  基本思想:计数排序不是基于比较的排序算法,核心在于将输入的数据值转化为键存储的额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数

  算法描述

  1、找出待排序的数组中最大和最小的元素

  2、统计数组中每个值为i的元素出现的次数,存入数组c的第i项

  3、对所有的计数累加(从c中的第一个元素开始,每一项和前一项相加)

  4、反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C【i】减去1

 

9、桶排序

  基本思想:捅排序是计数排序的升级版,利用了函数的映射关系,高效与否在于这个映射函数的确定。桶排序的工作的原理,假如输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶在分别排序(有可能在使用别的排序算法或者以递归方式继续使用桶排序进行排)

  算法描述:

  1、设置一个定量的数组当做空桶

  2、遍历输入数据,并且把数据数据一个一个放到对应的桶里去

  3、对每个不是空的桶进行排序

  4、从不是空的桶里把排好序的数据拼接起来

 

10、基数排序

  基本思想:基数排序是按照低位先排序,然后收集;在按照高位排序,然后在收集;以此类推,知道最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,在按照高优先级排序。最后的次序就是高优先级的在前,高优先级相同的低优先级高的在前。

  算法描述:

  1、取得数组的最大数,并取得位数

  2、a为原始数组,从最低位组成radix数组

  3、对radix进行计数排序(利用计数排序使用与小范围数的特点)

 

 

 

  

posted @   风中凌乱的猪头  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示