八大排序算法

一 .概述
八大排序算法包括
1)插入排序之直接插入排序(Straight Insertion Sort)
2)插入排序之希尔排序(Shells Sort)
3)选择排序之简单选择排序(Simple Selection Sort)
4)选择排序之堆排序(Heap Sort)
5)交换排序之冒泡排序(Bubble Sort)
6)交换排序之快速排序(Quick Sort)
7)归并排序(Merge Sort)
8 )桶排序/基数排序(Radix Sort)
二.详解
1.插入排序—直接插入排序(Straight Insertion Sort)
1)基本思想: 将一个数插入到前面已排序好的有序表中,从而得到一个新记录数增1的有序表。
要点:设立哨兵,作为临时存储和判断数组边界之用。
稳定排序:在原序列中遇到一个和插入元素相等的,那么把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,所以插入排序是稳定的。
2)代码

void print(int a[], int n ,int i){  
    cout<<i <<":";  
    for(int j= 0; j<n; j++){  
        cout<<a[j] <<" ";  
    }  
    cout<<endl;  
}  


void InsertSort(int a[], int n)  
{  
    for(int i= 1; i<n; i++){  
        if(a[i] < a[i-1]){ //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入  
            int j= i-1;   
            int x = a[i];        //复制为哨兵,即存储待排序元素  
            a[i] = a[i-1];           //先后移一个元素  
            while(x < a[j]){  //查找在有序表的插入位置  
                a[j+1] = a[j];  
                j--;         //元素后移  
            }  
            a[j+1] = x;      //插入到正确位置  
        }  
        print(a,n,i);           //打印每趟排序的结果  
    }  

}  

int main(){  
    int a[8] = {3,1,5,7,2,4,9,6};  
    InsertSort(a,8);  
    print(a,8,8);  
}  
对位置i的元素x进行插入分4步:保存->查找->移动->插入
Step1.先保存x.
Step2.对其左边位置[0,i-1]元素从右往左遍历,找出第一个比x小或等的元素xsmall,假设xsamll的位置为pos.
step3.将[pos+1,i-1]处的元素在插入前向后移动一位。
step4.把x插入到xsmall的后面,即把x放到pos+1的位置。

size_t findfirstminpos(vector<int>&a,size_t i)
{
    size_t k=i-1;
    while(a[k]>a[i])
        k--;
    return k;
}

void mov(vector<int> &a,size_t i,size_t j)
{   
    for(int k=j;k>=i;k--)
        a[j+1]=a[j];
}

void InsertSort(vector<int>& a)
{
    size_t asize=a.size();
    for(size_t i=1;i<asize;i++){
        int temp=a[i];
        size_t pos=findfirstminpos(a,i);
        mov(a,pos+1,i-1);
        a[pos+1]=temp;  
    }

}

2.希尔排序
1)基本思想
又叫缩小增量排序,将待排序数列按增量分成若干个子序列,利用直接插入排序思想对子序列进行排序。
2)代码

int findfirstmin(int a[],int n,int stepp,int i)
{//在a中i以前找比i位置元素小或等的元素位置
    int pos=i-stepp;
    while(pos>0&&a[pos]>a[i]) pos-=stepp;
    return pos;
}
void mov(int a[],int stepp,int s,int e)
{//将数组元素a[s...e]都向后移动一位,流出s的位置
    while(e>=s) 
    {
        a[e+stepp]=a[e];
        e-=stepp;
    }
}
void shellSort(int a[],int n,int stepp)
{
    for(int i=1+stepp;i<=n;i++)
    {
        int k=a[i];
        int pos=findfirstmin(a,n,stepp,i);
        mov(a,stepp,pos+1,i-1);
        a[pos]=k;
    }
}
void shellInserSort(int a[],int n,int step[],int m)
{
    for(int i=0;i<m;i++)
        shellSort(a,n,step[i]);
}

3.简单选择排序

4.堆排序
1)基本思想
在堆中,堆的根节点的元素值一定是所有节点元素的最大值或最小值。如果将堆中根节点输出之后,将其余n-1个节点的元素值重新建立一个堆,则新堆的堆顶元素值是次大(或次小)值,将该堆顶元素输出。这样重复建堆并输出堆顶元素的过程称为堆排序。

2)
a.建堆:从最后一个非叶子节点开始调整堆,使得从该节点往下都是堆(叶子节点相当于一个堆)
b.调整堆函数:void AdjustHeap(int a,int s,int m) 第二个参数表示以s为根调整建立堆,m是要调整的a的总长度。从s开始调整说明s的下层都已经调整好了,需要把s插入到下层的某个位置。
也就是在a[s—m]中a[s]是唯一一个不符合堆规则的元素,需要调整。

3)给出一列有n个元素的数组(从位置1开始放),利用堆排序法进行排序的过程:
step1 由这n个数建立一个堆(本文用大顶堆);
step2 当最后一个元素还没有走到第一个元素的时候
step2.1 输出堆顶元素(将堆顶元素和最后一个元素交换);
step2.2 调整堆。

void adjustHeap(int a,int s,int n)   //调用函数1
{
    int j=2*s;
    int k=a[s];

    while(j<=n){
        if((j+1<=n)&&a[j+1]>a[j]) 
            j++; //j指向s子节点较大的那个
        if(a[j]>a[s]) a[s]=a[j];
        else break;
        s=j;
        j=2*s;
    } 
    a[s]=k; 
 }

void createHeap(int a[],int n)//调用函数2
{
    for(int s=n/2;s>=1;s--)
        adjustHeap(a,s,n);
}

void heapSort(int a[],int n)    //主排序
{
    createHeap(a,n);
    while(n>1)
    {
        swap(a[1],a[n]);
        adjustHeap(a,1,n-1);
        n--;
    }
}

5.冒泡排序

6.快速排序(不稳定排序)
1)基本思想
数组data[1…n]放n个待排序元素,初始时,令left=1,right=n,令a[1]作为参考元素,然后按以下操作:
a.从right位置往前减,依次与参考元素比较,若大于等于参考则继续前移,若小于则将right处元素移到left处,令left++,进入b步骤。
b. 从left位置往后增,依次与参考元素比,若小于参考则继续后增,反之,将left处元素移到right处,令right–,进入a步骤。
2)代码
tips:一次快排使得枢轴前面的元素都小于枢轴元素,枢轴后面的元素都大于等于枢轴元素。

int partition(int a,int left,int right)//调用函数
{
    int pivot=a[left];
    while(left<right)
    {
        while(right>left&&a[right]>=pivot)
            right--;
        a[left]=a[right]; left++;
        while(left<right&&a[left]<pivot)
            left++;
        a[right]=a[left];right--;   
    }
    a[left]=pivot;
    return left;
}

void quickSort(int a[],int left,int right)  //主排序
{
    while(left<right)
    {   int pivot=partition(a,left,right);  //一次快排
        quickSort(a,left,pivot-1);
        quickSort(a,pivot+1,right);
    }   
}

7.归并排序

将两个有序的s[low…mid]和s[mid+1…high]子序列归并为一个有序的序列t[low…high]:

void merge(int s[],int t[],int low ,int mid ,int high)
{//被调函数
    int i=low,j=mid+1,k=low;
    while(i<=mid&&j<=high)
    {   
        if(s[i]>s[j]) t[k++]=s[i++];
        else          t[k++]=s[j++];
    }
    while(i<=mid) t[k++]=s[i++];
    while(j<=high) t[k++]=s[j++];
}
void mergeSort(int s[],int t[],int low,int high)
{//主调函数,将s[low...high]归并排序后放到t[low...high]
    int t2[1000];
    if(low=high) t[low]=s[low];
    else{
        int mid=(low+high)/2;
        mergeSort(s,t2,low,mid);
        mergeSort(s,t2,mid+1,high);
        merge(t2,t,low,mid,high);
    }
}

8 .桶排序/基数排序(Radix Sort)
方法一、用二维数组

int getSortTimes(int n) //最大数的位数即为桶排序的次数
{
    int count=0;
    while(n)
    {
        n=n/10;
        count++;
    }
    return count;
}
int getitsNum(int num,int n)//获取数num的第i位数,第1位为个位
{
    for(int i=1;i<n;i++)
        num=num/10;
    num=num%10;
    return num;
}
void distribute(int a[],int n,int buck[10][20],int pos,int index[10])
{//将数组a中的元素放入桶buck中,pos表示取哪一位的数字
    for(int i=0;i<n;i++)
    {
        switch(getitsNum(a,pos))
        {
            case 0:
            buck[0][index[0]++]=a[i];break;
            case 1:
            buck[1][index[1]++]=a[i];break; 
            case 2:
            buck[2][index[2]++]=a[i];break; 
            case 3;
            buck[3][index[3]++]=a[i];break;
            case 4:
            buck[4][index[4]++]=a[i];break;
            case 5:
            buck[5][index[5]++]=a[i];break; 
            case 6:
            buck[6][index[6]++]=a[i];break; 
            case 7:
            buck[7][index[7]++]=a[i];break;
            case 8:
            buck[8][index[8]++]=a[i];break;
            case 9:
            buck[9][index[9]++]=a[i];break; 
            default:
            break;
        }
    }
}

void collect(int a[],int n,int buck[10][20],int index[])
{
    int k=0;
    for(int i=0;i<10;i++)
    {   
        for(int j=0;j<index[i];j++)
        {
            a[k++]=buck[i][j];
            buck[i][j]=0;
        }
        index[i]=0;
    }
}

void radix_sort(int a[],int n)
{//主排序 函数
    int index[10]={0};
    int bucket[10][20];//一个10个桶,每个桶最多放20个数
    int max=a[0];
    for(int i=0;i<n;i++)
        if(a[i]>max) max=a[i];
    int sortTimes=getSortTimes(max);
    for(int i=0;i<sortTimes;i++)
    {
        distribute(a,n,bucket,i+1,index);
        connect(a,n,bucket,index);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值