zoukankan      html  css  js  c++  java
  • Java实现预排序

    1 问题描述
    在计算机科学中,预排序是一种很古老的思想。实际上,对于排序算法的兴趣很大程度上是因为这样一个事实:如果列表是有序的,许多关于列表的问题更容易求解。显然,对于包含了排序操作,这种算法的时间效率依赖于所选用的排序算法的效率。

    对于预排序的具体思想应用请参考下文。

    2 解决方案
    2.1 检验数组中元素的唯一性

    此问题,首先使用合并排序对数组中元素进行一次从小到大的排序,然后,依次检查数组中的元素,看是否有重复元素,如果有这说明该元素不具有唯一性,否则说明该数组中的所有元素具有元素的唯一性。

    package com.liuzhen.chapter6;
    
    public class PresortElementUniqueness {
        //归并排序
        public void mergeSort(int[] A){
            if(A.length > 1){
                int[] leftA = getHalfArray(A,0);   //数组A的左半部分
                int[] rightA = getHalfArray(A,1);  //数组A的右半部分
                mergeSort(leftA);
                mergeSort(rightA);
                getMerge(A,leftA,rightA);
            }
        }
        
        /*
         * 参数A:要进行折半的数组
         * 参数judge:judge == 0表示返回数组A左上半部分,judge != 0表示返回数组A的右半部分
         * 函数功能:把数组按照长度均分为上半部分和下半部分
         */
        public int[] getHalfArray(int[] A,int judge){
            int[] result;
            if(judge == 0){
                result = new int[A.length/2];
                for(int i = 0;i < A.length/2;i++)
                    result[i] = A[i];
            }
            else{
                result = new int[A.length - A.length/2];
                for(int i = 0;i < A.length - A.length/2;i++)
                    result[i] = A[i+A.length/2];
            }
            return result;
        }
        /*
         *参数A:给定待排序数组
         *参数leftA:数组A的左半部分
         *参数rightA:数组的右半部分
         *函数功能:返回数组A的从小到大排序
         */
        public void getMerge(int[] A,int[] leftA,int[] rightA){
            int i = 0;       //用于计算当前遍历leftA的元素个数
            int j = 0;       //用于计算当前遍历rightA的元素个数
            int count = 0;   //用于计算当前得到按从小到大排序的A的元素个数
            while(i < leftA.length && j < rightA.length){
                if(leftA[i] < rightA[j]){
                    A[count++] = leftA[i];
                    i++;
                }
                else{
                    A[count++] = rightA[j];
                    j++;
                }
            }
            if(i < leftA.length){
                while(i < leftA.length)
                    A[count++] = leftA[i++];
            }
            if(j < rightA.length){
                while(j < rightA.length)
                    A[count++] = rightA[j++];
            }
        }
        //判断数组A(PS:数组A已是有序数组)中元素是否具有唯一性
        public boolean judgeOnlyElement(int[] A){
            for(int i = 0;i < A.length-1;i++){
                if(A[i] == A[i+1])
                    return false;
            }
            return true;
        }
        
        public static void main(String[] args){
            PresortElementUniqueness test = new PresortElementUniqueness();
            int[] A = {3,2,1,8,7,4,3,6,1,7,3,3,7,7,7,7};
            test.mergeSort(A);
            System.out.println("使用归并排序后数组A的结果:");
            for(int i = 0;i < A.length;i++)
                System.out.print(A[i]+" ");
            if(test.judgeOnlyElement(A))
                System.out.println("
    数组A中的元素具有唯一性");
            else
                System.out.println("
    数组A中的元素不具有唯一性");
            int[] B = {9,8,7,6,5,4,3,2,1};
            test.mergeSort(B);
            System.out.println("使用归并排序后数组B的结果:");
            for(int i = 0;i < B.length;i++)
                System.out.print(B[i]+" ");
            if(test.judgeOnlyElement(B))
                System.out.println("
    数组B中的元素具有唯一性");
            else
                System.out.println("
    数组B中的元素不具有唯一性");
        }
    }
    

    运行结果:

    使用归并排序后数组A的结果:
    1 2 3 3 3 3 4 6 7 7 7 7 7 7 8 
    数组A中的元素不具有唯一性
    使用归并排序后数组B的结果:
    2 3 4 5 6 7 8 9 
    数组B中的元素具有唯一性
    

    2.2 模式计算
    在给定的数组列表中最经常出现的一个数值称为模式。例如,对于5,1,5,7,6,5,7来说,模式是5(如果若干个不同的值都是最经常出现的,它们中的任何一个都可以看作模式。)

    此处,首先对给定数组中元素使用合并排序进行从小到大排序,然后,依次遍历其中的元素,计算其中重复元素的最大个数,返回该元素的值,即为所求的模式。

    package com.liuzhen.chapter6;
    
    public class PresortElementUniqueness {
        //归并排序
        public void mergeSort(int[] A){
            if(A.length > 1){
                int[] leftA = getHalfArray(A,0);   //数组A的左半部分
                int[] rightA = getHalfArray(A,1);  //数组A的右半部分
                mergeSort(leftA);
                mergeSort(rightA);
                getMerge(A,leftA,rightA);
            }
        }
        
        /*
         * 参数A:要进行折半的数组
         * 参数judge:judge == 0表示返回数组A左上半部分,judge != 0表示返回数组A的右半部分
         * 函数功能:把数组按照长度均分为上半部分和下半部分
         */
        public int[] getHalfArray(int[] A,int judge){
            int[] result;
            if(judge == 0){
                result = new int[A.length/2];
                for(int i = 0;i < A.length/2;i++)
                    result[i] = A[i];
            }
            else{
                result = new int[A.length - A.length/2];
                for(int i = 0;i < A.length - A.length/2;i++)
                    result[i] = A[i+A.length/2];
            }
            return result;
        }
        /*
         *参数A:给定待排序数组
         *参数leftA:数组A的左半部分
         *参数rightA:数组的右半部分
         *函数功能:返回数组A的从小到大排序
         */
        public void getMerge(int[] A,int[] leftA,int[] rightA){
            int i = 0;       //用于计算当前遍历leftA的元素个数
            int j = 0;       //用于计算当前遍历rightA的元素个数
            int count = 0;   //用于计算当前得到按从小到大排序的A的元素个数
            while(i < leftA.length && j < rightA.length){
                if(leftA[i] < rightA[j]){
                    A[count++] = leftA[i];
                    i++;
                }
                else{
                    A[count++] = rightA[j];
                    j++;
                }
            }
            if(i < leftA.length){
                while(i < leftA.length)
                    A[count++] = leftA[i++];
            }
            if(j < rightA.length){
                while(j < rightA.length)
                    A[count++] = rightA[j++];
            }
        }
        
        //返回数组A(PS:数组A是有序数组)中模式
        public int presortMode(int[] A){
            int i = 0;
            int modeFrequency = 0;
            int modeValue = 0;
            while(i < A.length){
                int temp = i;
                int count = 0;
                while(temp < A.length && A[temp] == A[i]){
                    count++;
                    temp++;
                }
                if(count > modeFrequency){
                    modeFrequency = count;
                    modeValue = A[i];
                }
                i = i+count;
            }
            return modeValue;
        }
        public static void main(String[] args){
            PresortElementUniqueness test = new PresortElementUniqueness();
            int[] A = {3,2,1,8,7,4,3,6,1,7,3,3,7,7,7,7};
            test.mergeSort(A);
            System.out.println("使用归并排序后数组A的结果:");
            for(int i = 0;i < A.length;i++)
                System.out.print(A[i]+" ");
            System.out.println("
    数组A中模式为:"+test.presortMode(A));
            int[] B = {9,8,7,6,5,4,3,2,1};
            test.mergeSort(B);
            System.out.println("使用归并排序后数组B的结果:");
            for(int i = 0;i < B.length;i++)
                System.out.print(B[i]+" ");
            System.out.println("
    数组B中模式为:"+test.presortMode(B));
        }
    }
    

    运算结果:

    使用归并排序后数组A的结果:
    1 2 3 3 3 3 4 6 7 7 7 7 7 7 8 
    数组A中模式为:7
    使用归并排序后数组B的结果:
    2 3 4 5 6 7 8 9 
    数组B中模式为:1
    
  • 相关阅读:
    CF1539 VP 记录
    CF1529 VP 记录
    CF875C National Property 题解
    CF1545 比赛记录
    CF 1550 比赛记录
    CF1539E Game with Cards 题解
    CF1202F You Are Given Some Letters... 题解
    vmware Linux虚拟机挂载共享文件夹
    利用SOLR搭建企业搜索平台 之九(solr的查询语法)
    利用SOLR搭建企业搜索平台 之四(MultiCore)
  • 原文地址:https://www.cnblogs.com/a1439775520/p/12948045.html
Copyright © 2011-2022 走看看