排序算法汇总与实现

本文详细介绍了几种排序算法,包括插入排序、合并排序、堆排序和快速排序。插入排序通过模拟打牌插序过程实现,时间复杂度为O(n^2)。合并排序采用分治策略,时间复杂度为O(nlog2n)。堆排序是原地排序,时间复杂度同样为O(nlog2n)。快速排序在平均情况下的时间复杂度为O(nlog2n),通过随机化版本可以避免最坏情况。最后提到了线性时间复杂度的计数排序,适用于特定场景。
摘要由CSDN通过智能技术生成

排序算法汇总与实现

1.插入排序

问题描述:

输入:n个数( a 1 , a 2 , . . . . , a n a_1,a_2,....,a_n a1,a2,....,an

输出:输入序列的一个排序(即重新排序)( a 1 ′ , a 2 ′ , . . . a n ′ a_1',a_2',...a_n' a1,a2,...an),使得 a 1 ′ ≤ a 2 ′ ≤ a 3 ′ , . . . ≤ a n ′ a_1' \leq a_2' \leq a_3',... \leq a_n' a1a2a3,...an

思想:模拟打牌插序过程。输入的各数字是原地排序的(sorted in place),即这些数字就是在数组A中进行重新排序的,在任何时刻,至多只有其中的常数个数字是存储在数组之外的。数组被分为两部分A[1,j-1]的子数组构成左手中当前已排序好的牌(数组),元素A[j+1,n]对应仍然乱序的牌(数组)。j从2开始,每次讲A[j+1]插入A[1,j-1]数组中,经过外循环n次loop,完成排序。

例子:[5,2,4,6,1,3]

  • 当j=2时,排序顺序为[5|2,4,6,1,3] |左边为已经排好顺序的序列
  • 当j+1,5>2,所以排序序列变为[2,5|4,6,1,3]
  • 2<4<5,所以[2,4,5|6,1,3]
  • 5<6,[2,4,5,6|1,3]
  • 1<2,[1,2,4,5,6|3]
  • 2<3<4,[1,2,3,4,5,6]

代码实现:

def insertSoted(A:[int]):
    l = len(A)
    for j in range(1,l):
        key = A[j]
        i = j - 1
        while i >= 0 and A[i] > key:  #往子数组中插入,第二层循环
            A[i+1] = A[i]
            i = i -1
        A[i+1] = key
    return A

if __name__=='__main__':
    A = [5,2,4,6,1,3]
    d = insertSoted(A)

package joe.sorted;

import java.util.Arrays;


public class insertSoted {
   

    public static void main(String[] args){
   
        Integer[] integerArray = new Integer[]{
   5,2,4,6,1,3};
        insertSoted(integerArray);
        System.out.println(Arrays.toString(integerArray));
    }

    public static void insertSoted(Integer[] A){
   
         int i,j,key;
         int l = A.length;
         for (j=1;j<l;j++){
   
             key = A[j];
             i = j-1;
             while (i>= 0 && A[i] > key){
   
                 A[i+1] = A[i];
                 i = i - 1;
             }
             A[i+1] = key;
         }
    }
}

算法复杂度:

算法经历了2次循环,所以时间复杂度为: O ( n 2 ) O(n^2) O(n2)

2.合并排序

有很多算法在结构上是递归的:为了解决一个给定的问题,算法要一次或多次地递归调用其自身来解决相关的子问题。这些算法通常采用分治策略。

分治策略:将原问题划分为 n n n个规模较小而结构与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。

分治模式在每一层递归都有三个步骤:

分解(Divide):将原问题分解为一系列子问题

解决(Conquer):递归地解决各个子问题。若子问题足够小,则直接求解

合并(Combine):将子问题的结果合并成原问题的解。

合并排序:

分解:将 n n n个元素分成包含n/2个元素的子序列

解决:用合并排序法对两个子序列递归地排序

合并:合并两个已排序的子序列以得到的排序结果

在对子序列排序时,其长度为1时递归结束。单个元素被视为是已排序好的

关键步骤:合并两个已排序的子序列。为做合并,引入一个辅助过程MERGE(A,p,q,r),其中A:数组,p,q,r:下标。满足 p ≤ q ≤ r p \leq q \leq r pqr。该过程假设子数组A[p,q]和A[q+1,r]都已排序好,将其合并成一个已排序好的数组。

算法实现:

Java

package joe.sorted;

import org.apache.avro.generic.GenericData;

import java.util.Arrays;

public class mergeSorted {
   


    public static void sort(Integer[] A, int left, int right){
   
        if(left>=right){
   
            return;
        }
        int mid = (left+right)/2;
        System.out.println(left+','+mid+','+','+right+"dsfa");;
        sort(A,left,mid);
        sort(A,mid+1,right);
        merge(A,left,mid,right);

    }
    private static Integer[] merge(Integer[] A, Integer left, Integer mid, Integer right) {
   
        int i;
        int j;
        int n1 = mid-left+1;
        int n2 = right-mid;
        int[] L = new int[n1+1];
        int[] R = new int[n2+1];
        System.out.print(R.length+"sdf"+L.length);
        for (i=0;i<n1;i++){
   
            L[i] = A[left+i];
        }
        for(j=0;j<n2;j++){
   
            R[j] = A[mid+j+1];
        }
        L[n1] = (int)Double.POSITIVE_INFINITY; //重要
        R[n2] = (int)Double.POSITIVE_INFINITY;
        i = 0;
        j = 0;
        //System.out.println(Arrays.toString(L));
        for(int k=left;k<=right;k++){
   
            //System.out.println(R[j]);
            if(L[i]<=R[j]){
   
                A[k] = L[i];
                i++;
            }
            else {
   
                A[k] = R[j
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值