From 8b8c66e45faf6b0471847663015b5c466a30a2ae Mon Sep 17 00:00:00 2001 From: zan Date: Wed, 9 Dec 2020 08:02:09 +0800 Subject: [PATCH 1/2] [add] template code --- Heap.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Heap.java diff --git a/Heap.java b/Heap.java new file mode 100644 index 0000000..dd6535a --- /dev/null +++ b/Heap.java @@ -0,0 +1,30 @@ + +public class Heap>{ + public T[] heap; + public int SIZE; + public int count; + + Heap(int size){ + SIZE = size; + // reference: https://stackoverflow.com/questions/34827626/cannot-be-cast-to-ljava-lang-comparable + heap = (T[])new Comparable[SIZE]; + count = 0; + } + + + public void add (T item){ + if(count >= SIZE){ + // throw new Exception("Heap Overflow"); + System.out.println("Heap Full"); + return; + } + + } + + public void delete(T item){ + + } + + public void print(){ + } +} \ No newline at end of file -- Gitee From 08ff9f829a8eb644b6c22a4c4c9a84ebb4e88aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E7=81=BF=E7=83=BD?= <7857427+he_canfeng@user.noreply.gitee.com> Date: Tue, 15 Dec 2020 18:54:51 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 + .../Heap.java" | 92 ++++++++ .../MaxHeap.java" | 199 ++++++++++++++++++ .../HeapSort.java" | 70 ++++++ .../Merge.java" | 83 ++++++++ .../Top_K.java" | 59 ++++++ .../\347\256\200\344\273\213.txt" | 7 + 7 files changed, 518 insertions(+) create mode 100644 "\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/Heap.java" create mode 100644 "\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/MaxHeap.java" create mode 100644 "\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\345\240\206\346\216\222\345\272\217/HeapSort.java" create mode 100644 "\344\275\234\344\270\232/\350\277\233\351\230\266/\344\274\230\345\205\210\347\272\247\351\230\237\345\210\227\345\220\210\345\271\266K\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204/Merge.java" create mode 100644 "\344\275\234\344\270\232/\350\277\233\351\230\266/\345\212\250\346\200\201\346\225\260\346\215\256\351\233\206\345\220\210\347\232\204\346\234\200\342\274\244Top K/Top_K.java" create mode 100644 "\344\275\234\344\270\232/\350\277\233\351\230\266/\345\212\250\346\200\201\346\225\260\346\215\256\351\233\206\345\220\210\347\232\204\346\234\200\342\274\244Top K/\347\256\200\344\273\213.txt" diff --git a/README.md b/README.md index e931f2f..968250e 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,16 @@ 1. 实现⼀个小顶堆或者⼤顶堆 - (1) 定义堆的数据结构 + + + - (2) 实现入堆函数 + + + - (3) 实现出堆函数 + + 2. 实现堆排序 ### 进阶 diff --git "a/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/Heap.java" "b/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/Heap.java" new file mode 100644 index 0000000..f6ecd4e --- /dev/null +++ "b/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/Heap.java" @@ -0,0 +1,92 @@ +package heap; + //法一:实现⼀个大顶堆 2020.12.9 何灿烽 + + +public class Heap> { + public T[] heap; + public int SIZE; + public int count; + + Heap(int size) { + SIZE = size; + // reference: https://stackoverflow.com/questions/34827626/cannot-be-cast-to-ljava-lang-comparable + heap = (T[]) new Comparable[SIZE]; + count = 0; + + } + + + public void add(T item) { //添加 + + if (count >= SIZE) { + // throw new Exception("Heap Overflow"); + System.out.println("Heap Full"); + return; + } + + + heap[count] = item; + int index1 = count; + count++; + if (count > 1) { + while (index1 != 0) { + if (heap[index1].compareTo(heap[(index1 - 1) / 2]) > 0) { + T temp = heap[index1]; + heap[index1] = heap[(index1 - 1) / 2]; + heap[(index1 - 1) / 2] = temp; + } + index1 = (index1 - 1) / 2; + } + } + + } + + public void delete(){ //删除 + + heap[0]=heap[count-1]; + + heap[count-1]=null; + + for (int i = 0; i < heap.length - 1; i++){ + if (heap[i].compareTo(heap[(2*i)+1]) < 0){ + T temp=heap[i]; + heap[i] = heap[(2*i + 1)]; + heap[(2*i+1)] = temp; + } + if (heap[i].compareTo(heap[(2*i)+2])<0){ + T index=heap[i]; + heap[i]=heap[(2*i+2)]; + heap[(2*i+2)]=index; + } + return; + } + } + + public void print(){ + for (T num:heap){ + System.out.print(num+" "); + + } + } + + public static void main(String args[]){ + Heap heap1=new Heap(10); + + //测试操作 + heap1.add(16); + heap1.add(18); + heap1.add(33); + heap1.add(41); + heap1.add(76); + heap1.add(12); + heap1.add(23); + + System.out.printf("测试结果:"); + heap1.print(); + + heap1.delete(); + + + + } +} \ No newline at end of file diff --git "a/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/MaxHeap.java" "b/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/MaxHeap.java" new file mode 100644 index 0000000..811da09 --- /dev/null +++ "b/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\342\274\200\344\270\252\345\260\217\351\241\266\345\240\206\346\210\226\350\200\205\342\274\244\351\241\266\345\240\206/MaxHeap.java" @@ -0,0 +1,199 @@ +package heap; + //法二:实现⼀个大顶堆 2020.12.9 何灿烽 +import java.util.ArrayList; +import java.util.List; + +public class MaxHeap>{ + public T[] heap; //heap堆 + public int SIZE; //大小 + public int count; //数量 + + + + private List mHeap; // 存放元素的动态数组 + + public MaxHeap() { + this.mHeap = new ArrayList<>(); + } + + /* + * 大顶堆的向上调整算法(添加节点的时候调用) 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。 + * start 被上调节点的起始位置(一般为数组中最后一个元素的索引) + */ + protected void filterup(int start) { + + int c = start; // 需要调整的节点的初始位置 + int p = (c - 1)/2; // 当前节点的父节点的位置 + T tmp = mHeap.get(c); // 被调整节点的值 + + while (c > 0) { + // 父节点的值和被调整节点的值进行比较 + int cmp = mHeap.get(p).compareTo(tmp); + if (cmp >= 0) { + // 父节点大 + break; + } else { + // 被调整节点的值大,交换 + mHeap.set(c, mHeap.get(p)); + c = p; + p = (c - 1) / 2; + } + } + // 找到被调整节点的最终位置了 + mHeap.set(c, tmp); + } + + + /* + * 大顶堆的向下调整算法(删除节点的时候需要调用来调整大顶堆) + * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。 + * start被下调节点的起始位置(一般为0,表示从第1个开始) + * end截至范围(一般为数组中最后一个元素的索引) + */ + + protected void filterdown(int start, int end) { + + int c = start; // 被下调节点的初始位置 + int l = 2 * c + 1; // 左孩子节点的位置 + T tmp = mHeap.get(c); // 当前节点的值(大小) + + while (l <= end) { + // 当前节点的左右节点进行比较 + int cmp = mHeap.get(l).compareTo(mHeap.get(l + 1)); + // 取大的 + if (l < end && cmp < 0) { + l++; + } + // 当前节点和大的那个再比较一下 + cmp = tmp.compareTo(mHeap.get(l)); + if (cmp >= 0) { + // 当前节点大,不用动 + break; + } else { + // 当前节点小,交换 + mHeap.set(c, mHeap.get(l)); + c = l; // 更新当前节点的位置 + l = 2 * c + 1; // 更新当前节点的左孩子位置 + } + } + mHeap.set(c, tmp); + } + + + /*向大顶堆中添加新元素*/ + public void add(T data) { + int addIndex = mHeap.size(); // 获取插入的位置 + mHeap.add(data); //将新元素插入到数组尾部 + filterup(addIndex); //调用filterup函数,调整大顶堆 + } + + + /*删除大顶堆中的data节点,返回-1表示出错, 返回0表示删除成功*/ + public int delete(T data) { + + // 大顶堆空 + if (mHeap.isEmpty()) { + return -1; + } + + // 获取data在数组中的索引 + int index = mHeap.indexOf(data); + if (index == -1) { + return -1; + } + + // 堆中元素的个数 + int size = mHeap.size(); + // 删除了data元素,需要用最后一个元素填补,然后调用filterdown算法进行调整 + mHeap.set(index, mHeap.get(size - 1)); // 用最后一个元素填补 + mHeap.remove(size - 1); // 删除最后一个元素 + + if (mHeap.size() > 1 && index < mHeap.size()) { + // 调整成大顶堆 + filterdown(index, mHeap.size() - 1); + } + return 0; + } + + + public String toString() { + + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < mHeap.size(); i++) { + sb.append(mHeap.get(i) + " "); + } + return sb.toString(); + } + + /*原始大顶堆 + 90 + 80 70 + 60 40 30 20 + 10 50 + */ + //打印测试 + public static void main(String[] args) { + int a[] = {10, 40 ,30, 60, 90, 70, 20, 50 ,80}; //数组 + //构造一个大顶堆 + MaxHeap maxHeap = new MaxHeap<>(); + + //实现入堆操作 + System.out.println("依次入堆元素:"); + for(int i = 0; i < a.length; i++) { + System.out.println(a[i]); + maxHeap.add(a[i]); + } + + //生成的大顶堆 + System.out.println("原始生成的大顶堆:"); + System.out.println(maxHeap); + + //实现85的入堆操作 + int data = 85; + maxHeap.add(data); + + System.out.println("入堆元素" + data + "生成的大顶堆:"); + System.out.println(maxHeap); + + //实现90的出堆操作 + data = 90; + maxHeap.delete(data); + System.out.println("出堆元素" + data + "生成的大顶堆:"); + System.out.println(maxHeap); + + } + + + + + MaxHeap(int size){ + SIZE = size; + // reference: https://stackoverflow.com/questions/34827626/cannot-be-cast-to-ljava-lang-comparable + heap = (T[])new Comparable[SIZE]; //Comparable[SIZE]可比性大小 + count = 0; + } + + /*实现入堆函数 + public void add (T item){ + if(count >= SIZE){ + // throw new Exception("Heap Overflow"); 堆溢出 + + System.out.println("Heap Full"); //堆满 + + return; + + } + } +*/ + + /*实现出堆函数 + public void delete(T item){ + + } + */ + //打印 + public void print(){ + + } + +} \ No newline at end of file diff --git "a/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\345\240\206\346\216\222\345\272\217/HeapSort.java" "b/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\345\240\206\346\216\222\345\272\217/HeapSort.java" new file mode 100644 index 0000000..42f66b9 --- /dev/null +++ "b/\344\275\234\344\270\232/\345\237\272\347\241\200/\345\256\236\347\216\260\345\240\206\346\216\222\345\272\217/HeapSort.java" @@ -0,0 +1,70 @@ +package heap; + // 实现⼀个大顶堆的堆排序 2020.12.13 何灿烽 +public class HeapSort { //堆排序=HeapSort + + public static void print(int[] arr) { + for(int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + + public static void create_heap(int[] arr) { + for(int i =arr.length / 2-1; i >= 0; i--) { + fix_down(arr, i, arr.length-1); + } + } + + + public static void fix_down(int[] arr, int i, int end) { + int child = (i << 1) + 1; //当前节点的左孩子 + int temp = arr[i]; + + while(child <= end) { + // 选出两个孩子较大的那个 + if(child < end && arr[child+1] > arr[child]) { + child++; + } + if(temp < arr[child]) { + arr[i] = arr[child]; //孩子节点与当前节点替换 + i = child; + child = (i << 1) + 1; + }else { + break; + } + } + arr[i] = temp; + } + + + public static void head_sort(int[] arr) { + // 取出堆顶元素,与最后一个元素交换,调整堆 + for(int i = arr.length - 1; i >= 0; i--) { + int temp = arr[i]; //最后一个元素 + arr[i] = arr[0]; + arr[0] = temp; + fix_down(arr, 0, i-1); //注意此处是i-1; 刚刚交换后的最后一个元素不参与调整,即21不参与调整 + + } + } + //根据第一题的大顶堆进行测试 + public static void main(String[] args) { + //案例1 + int[] arr = {10, 40 ,30, 60, 90, 70, 20, 50 ,80}; + create_heap(arr); // 创建堆 + head_sort(arr); //sort堆分类 + System.out.print("1.堆排序:"); + print(arr); // 10 20 30 40 50 60 70 80 90 + + //案例2 + int[] arr1 = {5,4,3,2,1}; + create_heap(arr1); + head_sort(arr1); + System.out.print("2.堆排序:"); + print(arr1); // 1 2 3 4 5 + + + } + +} \ No newline at end of file diff --git "a/\344\275\234\344\270\232/\350\277\233\351\230\266/\344\274\230\345\205\210\347\272\247\351\230\237\345\210\227\345\220\210\345\271\266K\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204/Merge.java" "b/\344\275\234\344\270\232/\350\277\233\351\230\266/\344\274\230\345\205\210\347\272\247\351\230\237\345\210\227\345\220\210\345\271\266K\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204/Merge.java" new file mode 100644 index 0000000..55ede3d --- /dev/null +++ "b/\344\275\234\344\270\232/\350\277\233\351\230\266/\344\274\230\345\205\210\347\272\247\351\230\237\345\210\227\345\220\210\345\271\266K\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204/Merge.java" @@ -0,0 +1,83 @@ +package heap; + // 利用优先级队列合并K个有序数组 2020.12.13 何灿烽 + +/* 思路: + * 数组本身已经从小到大排好序,我们只需创建一个大小为k的最小堆, + * 堆中初始元素为k个数组中的每个数组的第一个元素, + * 每次从堆中取出最小元素(堆顶元素),将其存入并输出数组中, + * 将堆顶元素所在行的下一元素加入堆,重新排列出堆顶元素。 +*/ + +import java.util.Comparator; //Comparator=比较器 +import java.util.PriorityQueue; //PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。 +import java.util.Queue; + +class Element{ + public int a,b,c; + public Element(int a, int b, int val) { + this.a = a; + this.b = b; + this.c = val; + } +} +public class Merge { + + private Comparator MyCmp = new Comparator() { + //升序 + public int compare(Element o1, Element o2) { + return o1.c - o2.c; + } + }; + + + public int[] mergeKSortedArrays(int[][] arr) { //mergeKSortedArrays=合并K个排序数组 + if(arr == null) { + return new int[0]; + } + + int sum = 0; + + Queue q = new PriorityQueue( + arr.length,MyCmp + ); + + for(int i = 0; i < arr.length; i++) { + if(arr[i].length > 0) { + Element e = new Element(i, 0, arr[i][0]); + q.add(e); + sum += arr[i].length; //记录结果数组的总长度 + } + } + + int[] res = new int[sum]; + int idx = 0; + while(!q.isEmpty()) { + Element e = q.poll(); //弹出堆顶最小值 + res[idx++] = e.c; + // 当前结点被 PriorityQueue抛出来后,当前行的第二个结点加入 PriorityQueue + if(e.b + 1 < arr[e.a].length) { //将当前最小所在数组的下一个元素存入pq + q.add(new Element(e.a, e.b+1, arr[e.a][e.b+1])); + } + } + return res; + } + + //测试类 + public static void main(String[] args) { + Merge m = new Merge(); + int[][] arr = { + {3, 6, 9, 11}, + {2, 5, 15,17}, + {2, 6, 4, 22, 28}, + {21, 23, 12, 24}, + }; + + int[] res = m.mergeKSortedArrays(arr); + System.out.print("合并后:"); + for(int i=0; i list = Top_K.findTopK1(arr, 10); + //排序是为了方便观察 + Collections.sort(list); + System.out.println(list.toString()); + + + + /**需要排序的数组,需要的top K,返回top K的list集合*/ + public static List findTopK1(int[] input, int k) { + List list = new ArrayList<>(); + //这里其实不用重写compare方法,因为默认的就是从小到大排序 + PriorityQueue maxHeap = new PriorityQueue<>(k,(o1,o2)->o1-o2); + if (input == null || input.length < 1) { + return list; + } + for (int num : input) { + //在不够k之前,直接添加 + if (maxHeap.size() < k) { + maxHeap.offer(num); + } + //小顶堆的堆顶元素