编程之美2.5:寻找最大的K个数
引申:寻找第k大的数:
方法一:
// 选择第k大的数(通过改进快速排序来实现) public static void SelectShort(int[] array, int low, int high, int k, out int value) { int i = low; int j = high; int tempItem = array[low]; value = int.MinValue; while (low < high) { while (array[high] > tempItem && high > low) { high--; } if (low < high) { array[low] = array[high]; low++; while (array[low] <= tempItem && low < high) { low++; } array[high] = array[low]; high--; } } array[low] = tempItem; if (low == array.Length - k) { value = array[low]; return; } else if (low < array.Length -k) // 第k个元素在右分支中 { if (low + 1 < j) { SelectShort(array, low + 1, j, k, out value); } } else // (low > k-1)第k个元素在左分支中 { if (i < low - 1) { SelectShort(array, i, low - 1,k,out value); } } }
方法二:
借助编程之美的思想,求前k个最大的数,其中最小的就是。
// 创建最大堆 public static void CreateStack(int[] array, int startIndex, int lastIndex) { for (int root = lastIndex / 2; root >= startIndex; root--) { int currentRoot = root; int leftLeafIndex = 2 * root + 1; // 左孩子 int rightLeafIndex = leftLeafIndex +1; // 右孩子 while (leftLeafIndex <= lastIndex) { if (leftLeafIndex < lastIndex && rightLeafIndex <= lastIndex && array[leftLeafIndex] < array[rightLeafIndex])// 右孩子存在而且右孩子大于左孩子 { leftLeafIndex++; } if (array[leftLeafIndex] > array[root]) { int temp = array[root]; array[root] = array[leftLeafIndex]; array[leftLeafIndex] = temp; currentRoot = 2 * currentRoot + 1; //继续寻找是否到了叶子结点 leftLeafIndex = 2 * currentRoot + 1; } else { break; } } } } //堆排序 public static void StackSort(int[] arrary) { CreateStack(arrary, 0, arrary.Length - 1); int temp; for (int j = arrary.Length - 1; j > 0; j--) { temp = arrary[j]; arrary[j] = arrary[0]; arrary[0] = temp; CreateStack(arrary, 0, j - 1); } }