几大内部排序算法

这儿是我的笔记,希望大家可以友好交流!!谢谢#__#

好久没写了,但是没有松懈噢。看了数,AVL树,散列表,优先队列(堆)了,之后有时间会补记笔记的(!哈哈!),今天打算写一下各大排序算法,这也是之前上选修课一直没怎么明白的,冒泡和选择排序就不记了,这次重新学习,也没写这个。

先来说说最简单的排序算法之一——插入排序。以O(N2)时间限运行。我的理解是对于第P躺排序其实就是将第p个元素插入一个由源数组前p+1个元素组成的新数组中的合适位置上,这样进行N-1躺排序后,整个数组就有序了。例如
数组A:10,4,5,2,7,8
则第一趟排序是将元素4插入在由10,4元素组成的新数组的合适位置,所以结果是4,10,5,2,7,8
以此类推:
第二趟:4,5,10,2,7,8
第三趟:2,4,5,10,7,8
第四趟:2,4,5,7,10,8
第五趟:2,4,5,7,8,10
代码如下:

void Insert_Sort(int *A,int N)
{
    int i = 0, j =0;
    if (N <0 ||A == NULL)
    {
        printf("数组有误\n");
        exit(0);
    }
    else
    {
        for( i = 1; i < N ;i++)
        {
            int tmp = A[i];
            for(j = i ;j-1>=0&&A[j-1] >tmp ; j--)
            {
                A[j] = A[j-1];
            }
            A[j] = tmp;
        }
    }

}

实际上,代码第二层for循环是可以精简的,但是为了和之后的希尔排序实现类似化,也为了好记,就没有精简了:
精简版的

 for( i = 1; i < N ;i++)
        {
            int tmp = A[i];
            for(j = i ;j>0 && A[j-1] > tmp ; j--)
            {
                A[j] = A[j-1];
            }
            A[j] = tmp;
        }

接下来是希尔排序:通过比较一定间隔的元素来工作,各躺比较所用的距离随算法进行而减小,直到只比较相邻元素的最后一趟排序为止(缩小增量排序)。希尔排序最坏的时间限是O(N2),一般在O(N3/2),虽然堆排序是O(NlogN),但是实际希尔排序比堆排序更常用,因为实际的堆排序并没有相想象中的快,而且编程也挺繁琐,没有希尔排序来得简洁。

希尔排序一般先确定如何给增量序列,一般我们就选择,d =N/2,d = d/2…1;
然后对于每个d,其实就是相当与(相当于从程序理解得出的结论)一躺排序,这一趟排序其实是对d个由N/d(或者N/d-1)个元素组成的独立数组进行插入排序的过程。

设A:49,38,65,97,76,13,27,49,55,04
1:对于d = 5(N/2);
分成49与13;38与27;65与49;97与55;76与04;
分别插入排序得到
(这么看从每躺前的结果看,如A第一个49在第一组和13,所以49处是13,接下来是38,在第二组取最小的27,所以38处是27,;接着是65,在第三组,49最小,所以65处是49。。)
A1:13,27,49,55,04,49,38,65,97,76;
2:然后d=3;
由A1分成组:
13,55,38,76; 27,05,65; 49,49,97;
分别插入排序得到(按之前的看法,13在第一组且最小,所以不动;27在第二组,最小的是05,所以第二个不在是27,而是05,以此类推。。。)
13,04,49,38,27,49,55,65,97,76
d = 1
…..

void Xier_Sort(int *A,int N)
{
    int d = 0,i = 0, j =0,tmp = 0;
    if (N <= 0||A == NULL)
    {
        printf("Êý×éÓÐÎó\n");
        exit(0);
    }
    else
    {
        for(d = N/2;d >= 1;d/=2)
            {
                tmp = A[i];
                //j-d >= 0检测不要越0极限,一定用的是d,而不是i
                for(j = i;j-d >= 0 && A[j-d] > tmp; j=j-d)
                {
                    A[j] = A[j-d];
                }
                A[j] = tmp;
            }
        }

    }

}

容易出错的地方时内循环将d写成i,很可能没有很好的理解这个过程。
最后粘贴下测试代码,在后面的几大排序快速排序,归并排序,推排序,这个测试代码仍然适用,只需将其他的注释即可。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include"charu.h"
#include"xier.h"
#include"duipaixv.h"
#include"merge.h"
int main()
{
    #define N 10
    srand(time(0));
    int i = 0;
    int a[N] = {0};
    printf("еепРг╟\n");
    for(i = 0; i< N ;i++)
    {
        a[i] = rand() % N;
        printf("%d\t",a[i]);
    }
    //Insert_Sort(a,sizeof(a)/sizeof(a[0]));
    //Xier_Sort(a,sizeof(a)/sizeof(a[0]));
    //Quick_Sort(a,sizeof(a)/sizeof(a[0]));
    //Heap_Sort(a,N);
    Merge_Sort(a,N);
    printf("еепР╨С\n");
    for(i = 0; i< N ;i++)
    {
        printf("%d\t",a[i]);
    }

}

这篇先记到这(#__#)!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值