zoukankan      html  css  js  c++  java
  • 【基础算法】排序-复杂排序之二(找出第K大的数)

    切割的思想是高速排序最精髓的地方。每一次切割出来的元素K一个排在第K位,所以利用这样的思想我们至少知道3点

    1. 被切割出来的元素K最后一定排在第K位。

    2. 在K左边的元素一定比K小或者相等。

    3. 在K右边的元素一定比K大或者相等。

    所以我们能够通过这些性质定位到随意一个元素。

    比方我们partition完一个数组后,得到A={5,3,4,2,6,8,10,12,11,9}

    A[K]=8,所以我们知道排好序后的A[5]=8, A[4]一定在8左边,A[6]一定在8右边

    所以,我们一定知道8这个数是数组里第5+1小的数。第10-5大的数

    所以我们得出 假设切割出来的数A[K]=X, 那么X一定是数组里的第K+1位,也就是第K+1小的数

    假设数组的长度为N,那么X就是数组里第N-K大的数

    以下是切割的代码

    	public static int partition(int[] array, int left, int right) {
    		int i = left;
    		int j = right + 1;
    
    		while (true) {
    
    			while (more(array[left], array[++i]))
    				if (i == right)
    					break;
    			while (more(array[--j], array[left]))
    				if (j == left)
    					break;
    
    			if (i >= j)
    				break;
    			exchange(array, i, j);
    		}
    		exchange(array, left, j);
    		return j;
    	}

    接下来就是怎样在切割后定位其它的元素了?

    假设我们定位了A[K]=X,发现目标元素O比X大,那么就在右边找,left=K+1,假设比X小,那么就在左边找。right=K-1,否则定位成功

    	public static int select(int[] array, int k) {
    		int left = 0;
    		int right = array.length - 1;
    		while (left < right) {
    			int j = partition(array, left, right);
    			if (j < k)
    				left = j + 1;
    			else if (j > k)
    				right = j - 1;
    			else
    				return array[k];
    		}
    		return array[k];
    	}

    以下给出完整代码,仅供大家參考

    	// compare
    	public static boolean more(int v, int w) {
    		return v > w;
    	}
    
    	// exchange
    	public static void exchange(int[] array, int i, int j) {
    		int temp = array[i];
    		array[i] = array[j];
    		array[j] = temp;
    	}
    
    	public static int partition(int[] array, int left, int right) {
    		int i = left;
    		int j = right + 1;
    
    		while (true) {
    
    			while (more(array[left], array[++i]))
    				if (i == right)
    					break;
    			while (more(array[--j], array[left]))
    				if (j == left)
    					break;
    
    			if (i >= j)
    				break;
    			exchange(array, i, j);
    		}
    		exchange(array, left, j);
    		return j;
    	}
    
    	public static int select(int[] array, int k) {
    		int left = 0;
    		int right = array.length - 1;
    		while (left < right) {
    			int j = partition(array, left, right);
    			if (j < k)
    				left = j + 1;
    			else if (j > k)
    				right = j - 1;
    			else
    				return array[k];
    		}
    		return array[k];
    	}
    



  • 相关阅读:
    Oracle EXPDP/IMPDP示例
    Oracle修改日志归档模式、归档路径以及空间大小的相关测试
    CentOS6.8 安装 Oracle11.2.0.4
    安装ORACLE时 各Linux版本下载地址
    Oracle数据库导入报ORA-39083处理
    oracle跨平台数据迁移 expdp/impdp 字符集问题 导致ORA-02374 ORA-12899 ORA-02372
    ASM路径问题导致数据库不能正常启动 -- 报:ORA-03113: end-of-file on communication channel
    oralce11g RAC 启动后 CRS-0184: Cannot communicate with the CRS daemon.
    Oracle 11g安装时针对不同操作系统所需的依赖包查询地址
    关于oracle RAC心跳线采用直连 还是交换机连接的建议
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6786128.html
Copyright © 2011-2022 走看看