排序算法归总

交换类排序

1.冒泡排序(n*n)

第一轮交换的区间 0~N-1,最大数放到第N-1位置
.1第一个数与第二数比较,谁大放后面,
.2.然后第二个数与第三个数比较,谁大放后面
.3.依次交换,最大的数放到数组最后面
第二轮交换区间0~N-2,最大数放大第N-2位置

最后一轮 确定第1位和第2位值

2.快速排序(n*logN)

第一步,随机找出一个数,通过比较比这数大的放右边,比该数小的放左边
第二步,递归对左右区间分别进行步骤一
第三步,左右区间只有一位数时候停止

void QSort(int A[],int low,int high)
    //对数组A[low,...,high]
    {
        if(low<high)
        {
            int n;
            n=Partition(A,low,high);
            QSort(A,low,n-1);
            QSort(A,n+1,high);
        }
    }
    int Partition(int A[],int low,int high)
    //交换数组A[low,...,high]的记录,支点记录到位,并返回其所在位置,此时
    //在它之前(后)的记录均不大(小)于它
    {
        int key=A[low];
        while(low<high)
        {
            while(low<high&&A[high]>=key)
                high--;
            A[low]=A[high];
            while(low<high&&A[low]<=key)
                low++;
            A[high]=A[low];
        }
        A[low]=key;
        return low;
    }
选择类排序

1.直接选择排序(n*n)

第一轮选择区间0~N-1,选择出最小的值,放到位置0
第二轮选择区间1~N-1, 选择出最小的值,放到位置1

最后一轮区间N-2~N-1,最小的数(数组中最大的)放到位置N-1

2.堆排序(n*logN)

第一步:将无序序列构成一个堆,根据升序降序选择大根堆或小根堆
第二步:将堆顶元素与末尾元素交换,然后将最大元素沉到数组末端
第三步:此时重新调整堆结构(堆数量减一),执行第二步,直到堆中只剩下一个元素
构建堆的时间复杂度o(n) 循环n-1 次,每一次时间复杂度logN,总时间复杂度:nlogN-logN.

void Hsort(int[] arr){
    for(int i=arr.length/2-1;i>=0;i--){//构建大根堆
        adjustHeap(arr,i,arr.length);
    }
    for(int j=arr.length-1;j>0;j--){//堆首元素与推尾交换,剩下n-1继续构建大根堆,依次达到排序效果
        swap(arr,0,j);
        adjustHeap(arr,0,j);
    }
}

void adjustHeap(int[] arr,int i,int length){
    int temp = arr[i];
    for(int k=i*2+1;k<length;k=k*2+1){//每次如果发生了当前结点与孩子结点的交换,则要考虑交换后的孩子结点(值被交换了)与其孩子结点是否满足堆定义
    if(k+1<length && arr[k]<arr[k+1])
        k++;
    if(arr[k]>temp){//结点发生交换,循环继续,对交换后的孩子结点进行调整
        arr[i]=arr[k];
        i=k;
    }else{break;}
    arr[i]=temp;
}

归并类排序

1.归并排序(n*logN)

第一步,让数组中每一个数独立成为一个区间
第二步,相邻长度为一的区间进行合并,形成长度为2的有序序列

最后一步,将相邻长度n/2 的两个区间进行合并,形成长度为n的有序序列。

void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
        }
    }
void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}
插入类排序

1.直接插入类排序(n*n)

第一次插入区间0~0,如果比0位置上元素小,放入到0位置。
第二次插入区间0-1,从1~0开始比较,直到找出小于位置2元素所在位置,插入到其后面.

最后一次插入区间0-N-2,从N-2~-0开始比较,直到找出小于位置N-1元素所在位置,插入到其后面。

2.希尔排序

第一轮,选择步长 gap1=N/2,对数组中的每一个元素,分别与前面第gap1 个元素做比较,如果比其小则交换,再与交换后位置的前第gap1个元素做比较,遇到越界则结束。
第二轮,选择步长gap2=gap1/2,操作过程同上
知道gap==1,做最后一次类似插入类排序实现整体排序。

总结

交换类排序,指的是满足某一条件即发生两个数发生交换,而这些条件往往而不需要考虑全局情况。比如冒泡排序中比相邻的大,快速排序中比特定值大。

选择类排序,同样满足某一个条件发生交换,这里的条件往往是全局的条件按,比如推排序中每次选择最小的/最大的值,直接选择排序每次选择最小的放左边。

插入类排序,可以任务是交换类排序的升级,满足条件后不是交换而是插入到某一个位子。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值