七大内排序

我们更加排序记录是否全部放置在内存中,将排序分为内排序和外排序,这里我们主要了解七个经典的内排序:插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序

对于一个问题,选择哪种排序方法主要从以下两方面进行考虑:

  1.所选排序方法的时间复杂度。

  2.所选排序方法的稳定性。

对于一些问题,排序的稳定与否至关重要,因此我们有必要了介绍下排序的稳定性: 通俗的说,对于待排序序列a[],若有 a[i] == a[j],a[i]的位置在a[j]前面,若排序后a[i]的位置仍然在a[j]前面,那么这种排序稳定,否则即为不稳定排序。

 

1.插入排序:

  基本操作:将一个记录,插入到已经排好序的有序表中,从而得到一个新的,记录数增加1的有序表。

  最优时间复杂度:当序列已经为有序时,时间复杂度为O(n)

  最差时间复杂度:当序列为逆序时,时间复杂度为O(n^2)

  稳定性:稳定

  代码:

/////////////插入排序/////////////////
void insert_sort(int a[],int n)
{
    for(int i=1;i<n;i++)
    {
        int temp = a[i];
        int j = i;
        while(j>0 && a[j-1]>temp)
        {
            a[j] = a[j-1];
            j--;
        }
        a[j] = temp;
    }
}
View Code

 

2.希尔排序:

  基本操作:希尔排序是对插入排序改进。把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止(这里的增量可以理解为下标间隔)。

  最优时间复杂度:O(nlogn)

  最差时间复杂度:O(n^2)

  稳定性:不稳定

  代码:

///////////////希尔排序//////////////////
void shell_sort(int a[],int n)
{
    for(int d=n/2;d>0;d/=2)
    {
        for(int i=d;i<n;i++)
        {
            int temp = a[i];
            int j = i;
            while(j>=d && a[j-d]>temp)
            {
                a[j] = a[j-d];
                j -= d;
            }
            a[j] = temp;
        }
    }
}
View Code

 

3.选择排序:

  基本操作:在未排序的序列中找到一个最大/最小值,将其放在已排序的序列的末尾。

  最优时间复杂度:O(n^2)

  最差时间复杂度:O(n^2)

  稳定性:稳定

  代码:

//////////////选择排序////////////////
void select_sort(int a[],int n)
{
    for(int i=0;i<n-1;i++)
    {
        int k = i;
        for(int j=i+1;j<n;j++)
        {
            if(a[j] < a[k])
            {
                k = j;
            }
        }
        swap(a[k],a[i]);
    }
}
View Code

 

4.堆排序:

  基本操作:将待排序序列构造成一个堆,每次将堆首与堆尾交换并把堆的大小减一,并对交换后的堆进行维护。直至堆的大小为1。

  最优时间复杂度:O(nlogn)

  最差时间复杂度:O(nlogn)

  稳定性:不稳定

  代码:

/////////堆排序///////////
void heap_adjust(int a[],int root,int len) //维护堆
{
    int ls = root*2+1;
    int rs = root*2+2;
    if(ls < len)
    {
        int pos = ls;
        if(rs < len)
        {
            if(a[rs] > a[ls])
            {
                pos = rs;
            }
        }
        if(a[root] < a[pos])
        {
            swap(a[root],a[pos]);
            heap_adjust(a,pos,len);
        }
    }
}

void heap_sort(int a[],int n)
{
    for(int i=n/2; i>=0; i--)
        heap_adjust(a,i,n);

    for(int i=n-1; i>0; i--)
    {
        swap(a[0],a[i]);
        heap_adjust(a,0,--n);
    }
}
View Code

 

5.冒泡排序:

  基本操作:重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。

  最优时间复杂度:O(n)

  最差时间复杂度:O(n^2)

  稳定性:稳定

  代码:

//////////冒泡排序///////////////
void Bubble_sort(int a[],int n)
{
    for(int i=0;i<n;i++)
    {
        int flog = false;
        for(int j=n-1;j>i;j--)
        {
            if(a[j] < a[j-1])
            {
                swap(a[j],a[j-1]);
                flog = true;
            }
        }
        if(!flog)
            return;
    }
}
View Code

 

6.快速排序:

  基本操作:找到一个基准数,将小于基准数的元素放在基准数的左边,大于基准数的元素放在基准数的右边,此时基准便处于“正确”的位置,接下来对基准数的左、右两部分进行同样的操作。

  最优时间复杂度:大多数情况下时间复杂度为O(nlogn)

  最差时间复杂度:当待排序序列的所有元素值一样时,时间复杂度为O(n^2)

  稳定性:不稳定

  代码:

void quick_sort(int a[],int l,int r)
{
    if(l >= r)
        return;
    int temp = a[l];
    int i = l;
    int j = r;
    while(i < j)
    {
        while(i<j && a[j]>temp)
            j--;
        if(i < j)
            a[i++] = a[j];
        while(i<j && a[i]<temp)
            i++;
        if(i<j)
            a[j--] = a[i];
    }
    a[i] = temp;

    quick_sort(a,l,i-1);
    quick_sort(a,i+1,r);
}
View Code

 

7.归并排序:

  基本操作:采用分治的策略,并将已经排好序的两个序列通过归并操作,形成一个新的有序序列

  最优时间复杂度:O(nlogn)

  最差时间复杂度:O(nlogn)

  稳定性:稳定

  代码:

void Merge(int a[],int l,int mid,int r)
{
    int len1 = mid - l + 1;
    int len2 = r - mid;
    int *L = new int[len1];
    int *R = new int[len2];

    for(int i=0;i<len1;i++)
        L[i] = a[l+i];
    for(int i=0;i<len2;i++)
        R[i] = a[mid+1+i];

    int pos1 = 0;
    int pos2 = 0;
    int k = l;

    while(pos1<len1 && pos2<len2)
    {
        if(L[pos1] < R[pos2])
        {
            a[k++] = L[pos1++];
        }

        else
        {
            a[k++] = R[pos2++];
        }
    }

    while(pos1 < len1)
    {
        a[k++] = L[pos1++];
    }

    while(pos2 < len2)
    {
        a[k++] = L[pos2++];
    }
    delete []L;
    delete []R;
}

void Merge_sort(int a[],int l,int r)
{
    if(l >= r)
        return;
    int mid = (l+r)/2;
    Merge_sort(a,l,mid);
    Merge_sort(a,mid+1,r);
    Merge(a,l,mid,r);
}
View Code

 

posted @ 2018-02-27 01:30  声声醉如兰  阅读(353)  评论(0编辑  收藏  举报