《数据结构与算法分析 Java语言描述》选择问题

目录

选择问题

原题目

代码


最近看《数据结构与算法分析 Java语言描述(原书第3版)》一书,在做练习题1.1时,从网上找答案,发现有同学已经给出了答案(连接:https://blog.csdn.net/weixin_42675298/article/details/105578768),但运行程序发现程序有问题,这里重新写了程序。

选择问题

设有一N个元素的数组,要确定其中第k个最大者,我们称之为选择问题(selection problem)。书中提供了2个解决方案。方案一、将这个数组以递减顺序排序,然后返回位置k-1上的元素(数组下标以0为开始)。方案二、将数组前k个元素到一个数组t中,然后以递减顺序对t数组排序。接着,将剩下的元素在逐个读取,当读取到的新元素小于数组t中的第k-1个元素则忽略之,否则就将其放到数组t中的正确位置上,并将数组t中的一个元素挤出数组。当算法结束时,位于第k-1个位置上的元素作为答案返回。

原题目

编写一个程序解决选择问题。令k=N/2。画出表格显示程序对于N种不同的值的运行时间。

代码

这里的代码选择的是方案二,只打印出每种不同值数组找到结果花费的时间和结果(不绘制表格),另外有附加的校验对比结果。注意,这里的代码

只是对书中方案二的实现,不考虑方案的执行效率。

import java.util.Arrays;
import java.util.Random;

/**
 * 1 确定 N 个数中第 K 个最大值 
 * 2 根据《数据结构与算法分析-Java语言描述》将前K个数读入一个数组,使用冒泡排序递减 
 * 3 将剩下的元素逐个读入
 * 4 如果新元素小于第 K 个元素,忽略;否则将新元素插入正确的位置
 */

public class SelectProblem {
	public static final Random RANDOM = new Random(47);

	public static void main(String[] args) {
		test1();
		test2();
//		test3();
	}
	
	// 设N = 6
	public static void test1() {
		System.out.println("使用逆向的冒泡");
		for (int i = 0; i < 6; i++) {
//			int[] arr = createArray(RANDOM.nextInt(100000));
//			int[] arr = new int[] {3,1};
//			int[] arr = new int[] {3,1,2};
//			int[] arr = new int[] {3,1,5,2};
//			int[] arr = new int[] {3,1,5,2,6};
//			if (arr.length <2) {
//				System.out.println("长度小于2的数组跳过");
//				continue;
//			}
			int[] arr = createArray(100000);
			int[] arr2 = Arrays.copyOf(arr, arr.length);
			int result = printResultReversion(arr);
			
			//对比排序取值
			Arrays.sort(arr2);
//			System.out.println(Arrays.toString(arr2));
			int k = arr2.length / 2;
			int kvalue = arr2[arr2.length-k];//排序后取第K大的数
			System.out.println("对比值:"+kvalue);
			System.out.println("结果是否一致:"+(result == kvalue));
			System.out.println("--------------------------------------");
		}
	}
	
	// 设N = 6
	public static void test2() {
		System.out.println("使用正向的冒泡");
		for (int i = 0; i < 6; i++) {
//			int[] arr = createArray(RANDOM.nextInt(100000));
//			int[] arr = new int[] {3,1};
//			int[] arr = new int[] {3,1,2};
//			int[] arr = new int[] {3,1,5,2};
//			int[] arr = new int[] {3,1,5,2,6};
//			if (arr.length <2) {
//				System.out.println("长度小于2的数组跳过");
//				continue;
//			}
			int[] arr = createArray(100000);
			int[] arr2 = Arrays.copyOf(arr, arr.length);
			int result = printResult(arr);
			
			//对比排序取值
			Arrays.sort(arr2);
//			System.out.println(Arrays.toString(arr2));
			int k = arr2.length / 2;
			int kvalue = arr2[arr2.length-k];//排序后取第K大的数
			System.out.println("对比值:"+kvalue);
			System.out.println("结果是否一致:"+(result == kvalue));
			System.out.println("--------------------------------------");
		}
	}
	
	// 设N = 6
	public static void test3() {
		System.out.println("使用不完整的正向冒泡——前K趟");
		for (int i = 0; i < 6; i++) {
//			int[] arr = createArray(RANDOM.nextInt(100000));
//			int[] arr = new int[] {3,1};
//			int[] arr = new int[] {3,1,2};
//			int[] arr = new int[] {3,1,5,2};
//			int[] arr = new int[] {3,1,5,2,6};
//			int[] arr = new int[] {100, 1, -299, 1024, 2, 4, 8, 16, 512, Integer.MAX_VALUE ,256, 876542, 0, 123, 999, 888};
//			int[] arr = new int[] {88916, 154140, 97511, 132322, 17704, 177383, 187706, 100575, 98410, 136342, 107674, 198804, 88950, 37826, 114322, 150896, 58033, 32984, 42344, 65810};
//			if (arr.length <2) {
//				System.out.println("长度小于2的数组跳过");
//				continue;
//			}
			int[] arr = createArray(100000);
			int[] arr2 = Arrays.copyOf(arr, arr.length);
			int result = printResultPart(arr);
			
			//对比排序取值
			Arrays.sort(arr2);
//			System.out.println(Arrays.toString(arr2));
			int k = arr2.length / 2;
			int kvalue = arr2[arr2.length-k];//排序后取第K大的数
			System.out.println("对比值:"+kvalue);
			System.out.println("结果是否一致:"+(result == kvalue));
			System.out.println("--------------------------------------");
		}
	}

	// 正向冒泡排序
	public static void sort(int[] values) {
		if (values == null || values.length < 2) {
			return;
		}
		for (int i = 0; i < values.length-1; i++) {
			for (int j = 0; j < values.length -i- 1; j++) {
				if (values[j] > values[j + 1]) {
					int temp = values[j];
					values[j] = values[j + 1];
					values[j + 1] = temp;
				}
			}
		}
	}

	// 逆向冒泡排序
	public static int[] reversionSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return arr;
		}
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = arr.length - 1; j > i; j--) {
				if (arr[j] > arr[j - 1]) {
					int t = arr[j];
					arr[j] = arr[j - 1];
					arr[j - 1] = t;
				}
			}
		}
		return arr;
	}
	
	// 不完整的正向冒泡排序,只执行k趟,找出前K个最大值
	public static int[] sortPart(int[] values, int k) {
		if (values == null || values.length < 2) {
			return values;
		}
		for (int i = 0; i < k; i++) {
			for (int j = 0; j < values.length -i- 1; j++) {
				if (values[j] > values[j + 1]) {
					int temp = values[j];
					values[j] = values[j + 1];
					values[j + 1] = temp;
				}
			}
		}
		return values;
	}
	
	// 不完整的逆向冒泡排序,只执行k趟,找出前K个最大值
	public static int[] reversionSortPart(int[] arr, int k) {
		if (arr == null || arr.length < 2) {
			return arr;
		}
		for (int i = 0; i < k; i++) {
			for (int j = arr.length - 1; j > i; j--) {
				if (arr[j] > arr[j - 1]) {
					int t = arr[j];
					arr[j] = arr[j - 1];
					arr[j - 1] = t;
				}
			}
		}
		return arr;
	}


	// 分批处理
	public static int select(int[] values) {
		if (values == null || values.length == 0) {
			throw new NullPointerException("values can't be null");
		}
		int k = values.length / 2;
		int[] temp = Arrays.copyOf(values, k);
//		System.out.println("原始数据values:" + Arrays.toString(values));
//		System.out.println("原始数据temp:" + Arrays.toString(temp));
		sort(temp);
//		System.out.println("排序后temp:" + Arrays.toString(temp));
		
		
		for (int i = k; i < values.length; i++) {
			if (values[i] <= temp[0]) {
				continue;
			}
			int indexLess = 0;
			for (int j = 1; j < temp.length; j++) {
				if (values[i] >= temp[j]) {
					indexLess = j;
					temp[j-1] = temp[j];
				} else {
					indexLess = j-1;
					break;
				}
			}
			temp[indexLess] = values[i];
		}
		
		//System.out.println("最终temp:" + Arrays.toString(temp));
		return temp[0];
	}
	
	// 分批处理
	public static int selectReversion(int[] values) {
		if (values == null || values.length == 0) {
			throw new NullPointerException("values can't be null");
		}
		int k = values.length / 2;
		int[] temp = Arrays.copyOf(values, k);
//		System.out.println("原始数据values:" + Arrays.toString(values));
//		System.out.println("原始数据temp:" + Arrays.toString(temp));
		reversionSort(temp);
//		System.out.println("排序后temp:" + Arrays.toString(temp));
		
		
		for (int i = k; i < values.length; i++) {
			if (values[i] <= temp[k-1]) {
				continue;
			}
			int indexLess = 0;
			for (int j = temp.length-2; j >= 0; j--) {
				if (values[i] >= temp[j]) {
					indexLess = j;
					temp[j+1] = temp[j];
				} else {
					indexLess = j+1;
					break;
				}
			}
			temp[indexLess] = values[i];
		}
		
//		System.out.println("最终temp:" + Arrays.toString(temp));
		return temp[k-1];
	}
	
	public static int selectPart(int[] values) {
		if (values == null || values.length == 0) {
			throw new NullPointerException("values can't be null");
		}
		int k = values.length / 2;
//		System.out.println("原始数据values:" + Arrays.toString(values));
		sortPart(values, k);
//		System.out.println("排序后values:" + Arrays.toString(values));
		int kvalue = values[values.length -k];
		return kvalue;
	}

	// 创建随机数组
	public static int[] createArray(int length) {
		int[] values = new int[length];
		for (int i = 0; i < length; i++) {
			values[i] = RANDOM.nextInt(length * 2);
		}
		return values;
	}
	// 使用逆向的冒泡
	public static int printResultReversion(int[] values) {
		System.out.println("长度:" + values.length);
		long start = System.currentTimeMillis();
		int kvalue = selectReversion(values);
		System.out.println("result:" + kvalue);
		System.out.println("用时:" + (System.currentTimeMillis() - start) + "ms");
//		System.out.println("--------------------------------------");
		return kvalue;
	}
	
	// 使用正向的冒泡
	public static int printResult(int[] values) {
		System.out.println("长度:" + values.length);
		long start = System.currentTimeMillis();
		int kvalue = select(values);
		System.out.println("result:" + kvalue);
		System.out.println("用时:" + (System.currentTimeMillis() - start) + "ms");
//		System.out.println("--------------------------------------");
		return kvalue;
	}
	
	// 使用不完整的正向冒泡(只排出前K趟)
	public static int printResultPart(int[] values) {
		System.out.println("长度:" + values.length);
		long start = System.currentTimeMillis();
		int kvalue = selectPart(values);
		System.out.println("result:" + kvalue);
		System.out.println("用时:" + (System.currentTimeMillis() - start) + "ms");
		System.out.println("--------------------------------------");
		return kvalue;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值