package heap; import java.util.Stack; public class LeftHeap { int num ; LeftHeap left ; LeftHeap right ; int npl ; public LeftHeap() {} public LeftHeap(int num, int npl) { this.npl = npl; this.num = num; } /** * 左式堆合并的非递归实现 */ public static LeftHeap merge_unrec(LeftHeap h1 , LeftHeap h2) { if(h1 == null || h2 == null) return h1 == null ? h2 : h1 ; Stack<LeftHeap> stack = new Stack<>() ; //用于保存每一级的父节点 while (h2 != null || !stack.isEmpty()) { if(h1 != null && h2 != null) { if(h1.num > h2.num) //确保h1为小值的堆,h2为大值的堆 { LeftHeap temp = h1 ; h1 = h2 ; h2 = temp ; } if(h1.left == null) //当小堆的左子树为空时, 直接将h2作为他的左子树即可, 由于仍不存在右子树, 所以npl无需更新 { h1.left = h2 ; h2 = null ; } else { stack.push(h1) ; //说明左右子树都存在, 此时应将h1保存, 让h1的右子树和h2进行合并 h1 = h1.right ; } } else //各级的父节点连接右子树 { if(h1 == null) { h1 = h2 ; h2 = null ; } while (!stack.isEmpty()) { LeftHeap heap = stack.pop() ; heap.right = h1 ; if(heap.left.npl < heap.right.npl) swapLR(heap) ; heap.npl = heap.right.npl+1 ; h1 = heap ; } } } return h1 ; } public static LeftHeap merge(LeftHeap h1 , LeftHeap h2) { if(h1 == null || h2 == null) return h1 == null ? h2 : h1 ; if(h1.num > h2.num) return merge1(h2 , h1) ; else return merge1(h1 , h2) ; } private static LeftHeap merge1(LeftHeap h1 , LeftHeap h2) { if(h1.left == null) h1.left = h2 ; else { h1.right = merge(h1.right , h2) ; if(h1.left.npl < h1.right.npl) swapLR(h1) ; h1.npl = h1.right.npl+1 ; } return h1 ; } private static void swapLR(LeftHeap h) { LeftHeap temp = h.left ; h.left = h.right ; h.right = temp ; } public static void inOrder(LeftHeap heap) { if(heap == null) return ; inOrder(heap.left); System.out.print(heap.num + " "); inOrder(heap.right); } public static void main(String[] args) { LeftHeap h1 = new LeftHeap(3, 1) ; LeftHeap h2 = new LeftHeap(10, 1) ; LeftHeap h3 = new LeftHeap(8, 0) ; LeftHeap h4 = new LeftHeap(21, 0) ; LeftHeap h5 = new LeftHeap(14, 0) ; LeftHeap h6 = new LeftHeap(17, 0) ; LeftHeap h7 = new LeftHeap(23, 0) ; LeftHeap h8 = new LeftHeap(26, 0) ; h1.left = h2 ; h1.right = h3 ; h2.left = h4 ; h2.right = h5 ; h3.left = h6 ; h5.left = h7 ; h6.left = h8 ; LeftHeap a = h1 ; h1 = new LeftHeap(6,2) ; h2 = new LeftHeap(12,1) ; h3 = new LeftHeap(7,1) ; h4 = new LeftHeap(18,0) ; h5 = new LeftHeap(24,0) ; h6 = new LeftHeap(37,0) ; h7 = new LeftHeap(18,0) ; h8 = new LeftHeap(33,0) ; h1.left = h2 ; h1.right = h3 ; h2.left = h4 ; h2.right = h5 ; h3.left = h6 ; h3.right = h7 ; h5.left = h8 ; LeftHeap b = h1 ; LeftHeap heap = merge_unrec(a , b) ; inOrder(heap) ; } }
左式堆合并的时间复杂度为O(N) , 由于n个节点的左式堆的右子树最多含有log(N+1)个节点, 而且每次合并都是与较小值堆的右子树进行比较, 所以为O(N)
时间: 2024-10-14 03:11:06