排序(2)二分排序、快速排序、归并排序

排序(2)–二分排序、快速排序、归并排序


*二分排序

/**
 * 二分排序中,关键字的比较次数采用折半查找,数量级为O(nlogn),
 * 但是元素移动次数为O(n^2),因此时间复杂度为O(n^2)。
 * @author yj
 */
public class BinarySort {
    /**
     * 二分法插入排序是在插入第i个元素时,对前面的0~i-1元素进行折半,
     * 先跟他们中间的那个元素比,如果小,则对前半再进行折半,否则对后半进行折半,
     * 直到left>right,然后再把第i个元素前1位与目标位置之间的所有元素后移,
     * 再把第i个元素放在目标位置上。
     */
    public static void binarySort(int[] source){
        int left,right,middle;//left>right说明找到了位置
        int temp;
        for(int i = 1;i<source.length;i++){
            left = 0;//初始化左指向首个元素
            right = i-1;//右指向需要插入元素的左侧
            temp = source[i];//记录需要排序的元素
            while(left<=right){
                middle = (right+left)/2;
                if(source[middle]>temp){//中间元素大于待插入元素,说明插入位置在middle左侧
                    right = middle -1;//将右指向为左半
                }else {
                    left = middle + 1;
                }
            }
            for(int j = i-1;j>=left;j--){//插入操作,将元素右移
                source[j+1]=source[j];
            }
            source[left] = temp;
            spy(source);//显示排序的过程
        }
    }
    /**
     * 方便观察每次排序,可以窥探数组排序的情况
     * @param source
     */
    public static void spy(int[] source){
        for(int k = 0;k<source.length;k++){
            System.out.printf(source[k]+"  ");  
        }
        System.out.println();
    }
}

快速排序:

/**
 * 平均时间复杂度为O(nlgn/ig2);最差为O(n^2);空间复杂度O(logn)
 * 是不稳定排序
 * 该方法的基本思想是:1.先从数列中取出一个数作为基准数。
 * 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
 * 3.再对左右区间重复第二步,直到各区间只有一个数。
 * @author yj
 */
public class QuickSort {
    /**
     * 快速排序
     * @param source
     * @param low
     * @param high
     */
    public static void quickSort(int[] source,int low,int high){
        int pivotpos;//记录基准位置
        if(low<high){
            pivotpos = partition(source,low,high);
            quickSort(source, low, pivotpos - 1);//左半边
            quickSort(source, pivotpos + 1, high);//右半边
        }
    }
    /**
     * 划分算法
     * @param source
     * @param i
     * @param j
     * @return i 基准位置
     */
    private static int partition(int[] source, int i, int j) {
        int pivot = source[i];//将第一个数据记录为基准
        while(i<j){
        while(i<j&&source[j]>=pivot){
            j--;
        }
        if(i<j)
            source[i++] = source[j];//相当于source[i] = source[j];i++
        spy(source);//打印排序情况
        while(i<j&&source[i]<=pivot){
            i++;
        }
        if(i<j)
            source[j--] = source[i];
        spy(source);//打印排序情况
        }
        source[i] = pivot;
        return i;
    }
    /**
     * 方便观察每次排序,可以窥探数组排序的情况
     * @param source
     */
    public static void spy(int[] source){
        for(int k = 0;k<source.length;k++){
            System.out.printf(source[k]+"  ");  
        }
        System.out.println();
    }
}

*归并排序

/**
 * 时间复杂度O(nlogn),空间复杂度O(n),是稳定的排序
 * @author yj
 */
public class MergeSort {
    public static void mergeSort(int[] s,int start,int end){
        if(start<end){//两路归并
            int middle = (start+end)/2;
            mergeSort(s,start,middle);
            mergeSort(s, middle+1, end);
            //将两组数据归并
            merge(s,start,middle,middle+1,end);
        }
    }
    /**
     * 两组数据归并
     * @param s
     * @param start1
     * @param end1
     * @param start2
     * @param end2
     */
    public static void merge(int[] s,int start1,int end1,int start2,int end2){
        int i,j;//数组1、2的两个游标
        i = start1;
        j = start2;
        int[] temp = new int[end2-start1+1];//建立一个数组为两个之和大小,归并到这个数组
        int k =0;
        while(i<=end1&&  j<=end2){
            if(s[i]>s[j]){
                temp[k] = s[j];
                k++;
                j++;
            }else{
                temp[k] = s[i];
                k++;
                i++;
            }
        }
        //将剩余的元素加入temp中
        while(i<=end1){
            temp[k] = s[i];
            k++;
            i++;
        }
        while(j<=end2){
            temp[k] = s[j];
            k++;
            j++;
        }
        //将temp中数据转移到原数组中
        for(int element :temp){
            s[start1] = element;
            start1++;
        }
        spy(s);
    }
    /**
     * 方便观察每次排序,可以窥探数组排序的情况
     * @param source
     */
    public static void spy(int[] source){
        for(int k = 0;k<source.length;k++){
            System.out.printf(source[k]+"  ");  
        }
        System.out.println();
    }
}
  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 二路归并排序是一种经典的排序算法,其运行结果取决于输入序列的大小和内容。下面是一个简单的示例,展示了如何使用 Python 实现二路归并排序并输出结果: ```python def merge_sort(arr): if len(arr) <= 1: return arr mid = len(arr) // 2 left = merge_sort(arr[:mid]) right = merge_sort(arr[mid:]) return merge(left, right) def merge(left, right): result = [] i = j = 0 while i < len(left) and j < len(right): if left[i] <= right[j]: result.append(left[i]) i += 1 else: result.append(right[j]) j += 1 result += left[i:] result += right[j:] return result arr = [4, 2, 7, 1, 3, 6, 5, 8] print(merge_sort(arr)) ``` 在这个例子中,我们将一个包含 8 个整数的数组 `[4, 2, 7, 1, 3, 6, 5, 8]` 作为输入序列进行排序。程序输出的结果是一个排好序的列表,即 `[1, 2, 3, 4, 5, 6, 7, 8]`。 请注意,程序的运行结果可能因输入序列的不同而有所不同。 ### 回答2: 二路归并排序是一种经典的排序算法,其基本思想是将待排序的序列不断地划分成较小的子序列,直到只剩下一个元素,然后再将这些子序列两两合并,直到最终得到有序的序列。 在进行二路归并排序时,首先将待排序的序列平均分成两部分,然后对每一部分分别进行二路归并排序,递归地将其划分为较小的子序列。接着,再对这些子序列进行两两合并,不断地将相邻的子序列合并为更大的有序序列,直到只剩下一个有序序列为止。 二路归并排序的运行结果是将输入序列重新排列成一个有序序列。具体步骤如下: 1. 将待排序序列分成两个子序列,分别进行二路归并排序。 2. 对每个子序列递归执行上述步骤,直到只剩下一个元素。 3. 对相邻的子序列进行两两合并,得到更大的有序序列。 4. 不断地执行步骤3,直到最终合并成一个有序序列。 二路归并排序的时间复杂度为O(nlogn),其中n表示待排序序列的长度。尽管它的时间复杂度相对较高,但由于它的稳定性和可预测性,二路归并排序被广泛应用于各种排序问题中。 总结而言,二路归并排序是一种高效、稳定的排序算法,它能够将待排序序列重新排列成一个有序序列。通过不断地划分和合并子序列,二路归并排序能够实现快速、准确地排序大规模数据。 ### 回答3: 二路归并排序是一种常用的排序算法,它将一个序列划分为两个子序列,分别对这两个子序列进行递归排序,然后将两个有序子序列合并,从而得到一个有序的序列。 具体运行过程如下: 1. 将待排序序列不断二分,直到每个子序列只有一个元素,即认为这个子序列是有序的。 2. 递归合并相邻的子序列,每次合并后得到的子序列长度是原来的两倍。 3. 不断地进行子序列的合并,直到最终得到一个完整有序的序列。 举例说明: 假设待排序序列为[5, 2, 9, 1, 6, 4, 8, 3, 7]。 1. 将序列二分为[5, 2, 9, 1]和[6, 4, 8, 3, 7]两个子序列。 2. 对两个子序列分别进行递归排序。 对左边子序列进行递归排序,将其划分为[5, 2]和[9, 1],再分别对两个子序列进行递归排序,得到[2, 5]和[1, 9]。 对右边子序列进行递归排序,将其划分为[6, 4, 8]和[3, 7],再分别对两个子序列进行递归排序,得到[4, 6, 8]和[3, 7]。 3. 将已排序的子序列进行合并。 先合并两个长度为1的子序列[2]和[5],得到[2, 5]。 再合并两个长度为1的子序列[1]和[9],得到[1, 9]。 合并两个长度为2的子序列[2, 5]和[1, 9],得到[1, 2, 5, 9]。 合并两个长度为3的子序列[4, 6, 8]和[3, 7],得到[3, 4, 6, 7, 8]。 4. 最后合并两个有序子序列[1, 2, 5, 9]和[3, 4, 6, 7, 8],得到完整有序序列[1, 2, 3, 4, 5, 6, 7, 8, 9]。 二路归并排序运行结果是将待排序序列按照从小到大的顺序进行了排序,得到一个有序的序列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值