LomutoPartition算法:计算中值和选择问题(Java实现)

 

文章目录

  • 一、问题描述
  • 二、解决方案
    • 1.计算中值问题
    • 2.选择问题

 

一、问题描述

1)中值问题是求一个n个数列表中某一数组下标k,它要求该下标元素比列表中的一半元素大,又比另一半元素小,这个中间的值被称为中值。

2)选择问题是求一个n个数列表的第k个最小元素的问题。

二、解决方案

1.计算中值问题

本文使用Lomuto划分算法思想,此处引用《算法设计与分析基础》第三版上一段文字介绍及配图,具体如下:

具体实现代码如下:

package com.liuzhen.chapter4;

public class MedianProblem {
    //Lomuto划分
    /*
     * 参数A:给定的随机数数组
     * 参数start:开始进行选择的数组元素位置
     * 参数end:最后一个进行选择的数组元素位置
     * 函数功能:返回A[start]到A[end]元素中间的某一元素位置result,使得  左边部分元素  < A[result] <=右边部分元素
     */
    public int LomutoPartition(int[] A,int start,int end){
        int begin = A[start];
        int result = start;
        for(int i = start+1;i <= end;i++){
            if(A[i] < begin){
                /*
                 * 一旦出现小于begin的元素,result向后移动一位;
                 * 出现大于的不移动,当再次出现小于begin的元素,result向后移动一位,
                 * 此时result恰好指向第一个大于begin的元素,此时执行swap(A,result,i)
                 */
                result = result + 1;     
                swap(A,result,i);
            }
        }
        swap(A,start,result);    
        return result;
    }
    //交换数组中位置为m和n上的元素值
    public void swap(int[] A,int m,int n){
        int temp = A[m];
        A[m] = A[n];
        A[n] = temp;
    }
    
    public static void main(String[] args){
        MedianProblem test = new MedianProblem();
        int[] A = {4,1,10,8,7,12,9,2,15};
        int result = test.LomutoPartition(A, 0, A.length-1);
        System.out.println("对数组进栈Lomuto划分后结果:");
        for(int i = 0;i < A.length;i++)
            System.out.print(A[i]+" ");
        System.out.println("\n"+"进行Lomuto划分后的数组中轴位置:"+result);
    }
}

运行结果:

对数组进栈Lomuto划分后结果:
2 1 4 8 7 12 9 10 15 
进行Lomuto划分后的数组中轴位置:2

2.选择问题

通过2.1 计算中值问题中Lomuto算法的运用,那么如何寻找n个元素中第k个最小元素呢?此处调用2.1中相关函数,具体实现代码如下:

package com.liuzhen.chapter4;

public class SelectProblem {
    //快速选择
    /*
     * 参数A:给定随机数数组
     * 参数k:要求输出的第k个最小元素
     * 函数功能:返回数组A的第k个最小元素的值
     */
    public int quickSelect(int[] A,int k){
        int start = 0;
        int end = A.length-1;
        int mid = new MedianProblem().LomutoPartition(A, start,end);
        while(true){
            if(mid > k-1){
                end = mid-1;
                mid = new MedianProblem().LomutoPartition(A, start,end);
            }
            else if(mid < k-1){
                start = mid+1;
                mid = new MedianProblem().LomutoPartition(A, start,end);
            }
            else
                break;
        }
        return A[mid];
    }
    
    public static void main(String[] args){
        SelectProblem test = new SelectProblem();
        int[] A = {4,1,10,8,7,12,9,2,15};
        int result = test.quickSelect(A, 5);
        System.out.println("对数组进行快速选择并执行划分后结果:");
        for(int i = 0;i < A.length;i++)
            System.out.print(A[i]+" ");
        System.out.println("\n"+"进行快速选择后得到数组第5最小元素(从小到大排序):"+result);
    }
}

运行结果:

对数组进行快速选择并执行划分后结果:
2 1 4 7 8 12 9 10 15 
进行快速选择后得到数组第5最小元素(从小到大排序):8

 

写在最后:参考博客文章https://www.cnblogs.com/liuzhen1995/p/6404833.html

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小夢夢啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值