C++排序:冒泡排序,简单选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序

1、排序的稳定性:

            假设 Ki=K(1≤i≤n,1≤j≤n,i≠j),在排序前的序列中 i<j,如果排序后 i 仍然领先于 j ,则所用排序方法稳定;反之若可能使排序后序列 j 领先 i,则所用排序方法不稳          定。

2、内排序与外排序

            内排序是在排序整个过程中,待排序的所有记录全部被放置在内存中;外排序是由于排序的记录个数太多,不能同时放置在内存,整个排序过程需要在内外村之间多次交换     数据才行。

      1)对于内排序,排序算法的性能主要受3个方面影响:1.时间性能;2.辅助空间(辅助存储空间);3)算法的复杂性(算法本身的复杂度)。

      2)根据排序过程中借助的主要操作,内排序分为:插入排序、交换排序、选择排序、归并排序。

      3)根据算法的复杂度分为两大类:1.简单算法:冒泡排序、简单选择排序、直接插入排序;2.改进算法:希尔排序、堆排序、归并排序、快速排序。

 

 

 

 

 

 

 

 

 

 

 

 

     

//按顺序输出数组
void print(int a[], int n)
{
    for(int i=0;i<n;i++)
    {
        cout<< a[i] <<" ";
    }
    cout<<endl;
}

//数组两元素的交换
void swap(int a[], int i, int j)
{
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}

1.冒泡排序:

//对数组a[]作交换排序(冒泡排序初级版)
void BubbleSort0(int a[], int n)
{
    for(int i=0;i<n-1;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            if(a[i]>a[j])
                swap(a,i,j);
        }
    }
}

//冒泡排序
void BubbleSort(int a[], int n)
{
    for(int i=0;i<n-1;i++)
    {
        for(int j=n-1;j>i;j--)
        {
            if(a[j]<a[j-1])
                swap(a,j,j-1);
        }
    }
}


//改进冒泡算法
void BubbleSort2(int a[], int n)
{
    int flag = 1;//flag做为标记
    for(int i=0;i<n-1&&flag==1;i++)
    {
        flag = 0;
        for(int j=n-1;j>i;j--)
        {
            if(a[j]<a[j-1])
            {
                swap(a,j,j-1);
                flag = 1;//有数据交换则flag为1
            }
        }
    }
}

2.简单选择排序:

//简单选择排序
void SelectSort(int a[], int n)
{
    int min;
    for(int i=0;i<n-1;i++)
    {
        min = i;
        for(int j=i+1;j<n;j++)
        {
            if(a[min]>a[j])
                min = j;
        }
        if(i != min)
            swap(a,i,min);
    }
}

3.直接插入排序:

//直接插入排序
void InsertSort(int a[],int n)
{
    for(int i=1;i<n;i++)
    {
        if(a[i]<a[i-1])
        {
            int temp = a[i];
            int j;
            for(j=i-1;a[j]>temp;j--)
            {
                a[j+1] = a[j];
            }
            a[j+1] = temp;
        }
    }
}

4.希尔排序:

//希尔排序
void ShellSort(int a[], int n)
{
    int num = n;
    int x;
    do
    {
        num = num/3 +1;
        for(int i=num;i<n;i++)
        {
            if(a[i]<a[i-num])
            {
                x = a[i];
                int j=i-num;
                for(;j>=0&&x<a[j];j-=num)
                    a[j+num] = a[j];
                a[j+num] = x;
            }
        }
    }
    while(num>1);
}

5.堆排序:

 1 //堆排序
 2 //使a[s,m]成为一个大顶堆
 3 //若根结点存在序号0处, i结点的父结点下标就为(i-1)/2,
 4 //i结点的左右子结点下标分别为2*i+1和2*i+2
 5 //如果根结点是从1开始,则左右孩子结点分别是2i和2i+1
 6 void HeadAdjust(int a[], int s, int m)
 7 {
 8     int temp = a[s];
 9     for(int j=2*s+1; j<=m; j*=2)
10     {
11         if(j<m && a[j]<a[j+1])
12             j++;
13         if(temp>=a[j])
14             break;
15         a[s] = a[j];
16         s = j;
17     }
18     a[s] = temp;
19 }
20 //对数组a进行堆排序
21 void HeadSort(int a[], int n)
22 {
23     for(int i=n/2;i>=0;i--)
24         HeadAdjust(a,i,n);
25     for(int i=n-1;i>0;i--)
26     {
27         swap(a,0,i);
28         HeadAdjust(a,0,i-1);
29     }
30 }

 

6.归并排序:

1)递归实现:

//归并排序
//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]
void Merge(int SR[], int TR[], int i, int m, int n)
{
    int j,k,x;
    for(j=m+1,k=i; i<=m && j<=n; k++)
    {
        if(SR[i] < SR[j])
            TR[k] = SR[i++];
        else
            TR[k] = SR[j++];
    }
    while(i<=m)
    {
        TR[k++] = SR[i++];
    }
    while(j<=n)
    {
        TR[k++] = SR[j++];
    }
}
//将SR[s..t]归并排序为TR1[s..t]
void MSort(int SR[], int TR1[], int s, int t)
{
    int m;
    int TR2[20];
    if(s==t)
        TR1[s]=SR[s];
    else
    {
        m = (s+t)/2;
        MSort(SR,TR2,s,m);
        MSort(SR,TR2,m+1,t);
        Merge(TR2,TR1,s,m,t);
    }
}
//对数组a[]进行归并排序
void MergeSort(int a[], int b[], int n)
{
    MSort(a,b,0,n-1);
}

2)非递归实现:

 

7.快速排序:

1)

//交换数组a[]中子集的记录,使枢轴记录到位,并返回其所在位置
//此时在它之前(后)的记录均不大(小)于它
int Partition(int a[], int low, int high)
{
    int pivotkey = a[low];
    while(low<high)
    {
        while(low<high && a[high]>=pivotkey)
            high--;
        swap(a,low,high);
        while(low<high && a[low]<=pivotkey)
            low++;
        swap(a,low,high);
    }
    return low;
}
//对数组a[]在子集a[low..high]作快速排序
void QSort(int a[], int low, int high)
{
    if(low<high)
    {
        int pivot = Partition(a,low,high);
        QSort(a,low,pivot-1);
        QSort(a,pivot+1,high);
    }
}
//对数组a[]作快速排序
void QuickSort(int a[], int n)
{
    QSort(a,0,n-1);
}

2)优化小数组时的排序方案(如果数组非常小时,快速排序反而不如直接插入排序来的更好):

//优化小数组时的排序方案
const int MAX_LENGTH_INSERT_SORT = 7;
void QSort1(int a[], int low, int high)
{
    if((high-low)>MAX_LENGTH_INSERT_SORT)
    {
        int pivot = Partition(a,low,high);
        QSort(a,low,pivot-1);
        QSort(a,pivot+1,high);
    }
    else
        InsertSort(a,high-low+1);
}

3)优化递归操作:

//优化递归操作
void QSort2(int a[], int low, int high)
{
    if((high-low)>MAX_LENGTH_INSERT_SORT)
    {
        while(low<high)
        {
            int pivot = Partition(a,low,high);
            QSort2(a,low,pivot-1);
            low = pivot+1;
        }
    }
    else
        InsertSort(a,high-low+1);
}

3)优化选取枢轴和不必要交换:

//优化选取枢轴和不必要交换
int Partition1(int a[], int low, int high)
{
    //优化选取枢轴
    int m = low+(high-low)/2;
    if(a[low]>a[high])
        swap(a,low,high);
    if(a[m]>a[high])
        swap(a,high,m);
    if(a[m]>a[low])
        swap(a,m,low);

    int pivotkey = a[low];
    int flag = pivotkey;//枢轴备份到flag
    while(low<high)
    {
        while(low<high && a[high]>=pivotkey)
            high--;
        a[low] = a[high];//采用替换而不是交换的方式
        while(low<high && a[low]<=pivotkey)
            low++;
        a[high] = a[low];//采用替换而不是交换的方式
    }
    a[low] = flag;//将枢轴数值替换回a[low]
    return low;
}

 

posted @ 2015-10-07 10:21  jx_yangbo  阅读(631)  评论(0编辑  收藏  举报