zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    数组小练习
    数组
    利用数组进行排序
    继承练习
    黄金分割点
    百万富翁-循环练习
    SelectedIndexChanged事件, SelectedValueChanged事件和SelectionChangeCommitted事件的区别及应用——c#
    进制转换以及与字符串之间转换——c#
    文件中的类都不能进行设计,因此未能为该文件显示设计器
    winfrom自绘窗体边框——c#
  • 原文地址:https://www.cnblogs.com/jx-yangbo/p/4858286.html
Copyright © 2011-2022 走看看