Binary Heap Implemented via a Binary Tree Structure

后端 未结 2 1109
借酒劲吻你
借酒劲吻你 2020-12-18 14:56

For an assignment, we were instructed to create a priority queue implemented via a binary heap, without using any built-in classes, and I have done so successfully by using

相关标签:
2条回答
  • 2020-12-18 15:27

    A tree implementation of a binary heap uses a complete tree [or almost full tree: every level is full, except the deepest one].
    You always 'know' which is the last occupied leaf - where you delete from [and modifying it is O(logn) after it changed so it is not a problem], and you always 'know' which is the first non-occupied leaf, in which you add elements to [and again, modifying it is also O(logn) after it changed].

    The algorithm idea is simple:
    insert: insert element to the first non-occupied leaf, and use heapify [sift up] to get this element to its correct place in the heap.

    delete_min: replace the first element with the last occupied leaf, and remove the last occupied leaf. then, heapify [sift down] the heap.

    EDIT: note that delete() can be done to any element, and not only the head, however - finding the element you want to replace with the last leaf will be O(n), which will make this op expensive. for this reason, the delete() method [besides the head], is usually not a part of the heap data structure.

    0 讨论(0)
  • 2020-12-18 15:48

    I really wanted to do this for almost a decade.Finally sat down today and wrote it.Anyone who wants it can use it.I got inspired by Quora founder to relearn Heap.Apparently he was asked how would you find K near points in a set of n points in his Google phone screen.Apparently his answer was to use a Max Heap and to store K values and remove the maximum element after the size of the heap exceeds K.The approach is pretty simple and the worst case is nlog K which is better than n^2 in most sorting cases.Here is the code.

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author Harish R
     */
    public class HeapPractise<T extends Comparable<T>> {
    
        private List<T> heapList;
    
        public List<T> getHeapList() {
            return heapList;
        }
    
        public void setHeapList(List<T> heapList) {
            this.heapList = heapList;
        }
    
        private int heapSize;
    
        public HeapPractise() {
            this.heapList = new ArrayList<>();
            this.heapSize = heapList.size();
        }
    
        public void insert(T item) {
            if (heapList.size() == 0) {
                heapList.add(item);
            } else {
                siftUp(item);
            }
    
        }
    
        public void siftUp(T item) {
            heapList.add(item);
            heapSize = heapList.size();
            int currentIndex = heapSize - 1;
            while (currentIndex > 0) {
                int parentIndex = (int) Math.floor((currentIndex - 1) / 2);
                T parentItem = heapList.get(parentIndex);
                if (parentItem != null) {
                    if (item.compareTo(parentItem) > 0) {
                        heapList.set(parentIndex, item);
                        heapList.set(currentIndex, parentItem);
                        currentIndex = parentIndex;
                        continue;
                    }
                }
                break;
            }
        }
    
        public T delete() {
            if (heapList.size() == 0) {
                return null;
            }
            if (heapList.size() == 1) {
                T item = heapList.get(0);
                heapList.remove(0);
                return item;
            }
            return siftDown();
        }
    
        public T siftDown() {
            T item = heapList.get(0);
            T lastItem = heapList.get(heapList.size() - 1);
            heapList.remove(heapList.size() - 1);
            heapList.set(0, lastItem);
            heapSize = heapList.size();
            int currentIndex = 0;
            while (currentIndex < heapSize) {
                int leftIndex = (2 * currentIndex) + 1;
                int rightIndex = (2 * currentIndex) + 2;
                T leftItem = null;
                T rightItem = null;
                int currentLargestItemIndex = -1;
                if (leftIndex <= heapSize - 1) {
                    leftItem = heapList.get(leftIndex);
                }
                if (rightIndex <= heapSize - 1) {
                    rightItem = heapList.get(rightIndex);
                }
                T currentLargestItem = null;
                if (leftItem != null && rightItem != null) {
    
                    if (leftItem.compareTo(rightItem) >= 0) {
                        currentLargestItem = leftItem;
                        currentLargestItemIndex = leftIndex;
                    } else {
                        currentLargestItem = rightItem;
                        currentLargestItemIndex = rightIndex;
                    }
                } else if (leftItem != null && rightItem == null) {
                    currentLargestItem = leftItem;
                    currentLargestItemIndex = leftIndex;
                }
                if (currentLargestItem != null) {
                    if (lastItem.compareTo(currentLargestItem) >= 0) {
                        break;
                    } else {
                        heapList.set(currentLargestItemIndex, lastItem);
                        heapList.set(currentIndex, currentLargestItem);
                        currentIndex = currentLargestItemIndex;
                        continue;
                    }
                }
            }
            return item;
    
        }
    
        public static void main(String[] args) {
            HeapPractise<Integer> heap = new HeapPractise<>();
    
            for (int i = 0; i < 32; i++) {
                heap.insert(i);
            }
            System.out.println(heap.getHeapList());
            List<Node<Integer>> nodeArray = new ArrayList<>(heap.getHeapList()
                    .size());
            for (int i = 0; i < heap.getHeapList().size(); i++) {
                Integer heapElement = heap.getHeapList().get(i);
                Node<Integer> node = new Node<Integer>(heapElement);
                nodeArray.add(node);
            }
            for (int i = 0; i < nodeArray.size(); i++) {
                int leftNodeIndex = (2 * i) + 1;
                int rightNodeIndex = (2 * i) + 2;
                Node<Integer> node = nodeArray.get(i);
                if (leftNodeIndex <= heap.getHeapList().size() - 1) {
                    Node<Integer> leftNode = nodeArray.get(leftNodeIndex);
                    node.left = leftNode;
                }
                if (rightNodeIndex <= heap.getHeapList().size() - 1) {
                    Node<Integer> rightNode = nodeArray.get(rightNodeIndex);
                    node.right = rightNode;
                }
            }
            BTreePrinter.printNode(nodeArray.get(0));
        }
    }
    
    public class Node<T extends Comparable<?>> {
        Node<T> left, right;
        T data;
    
        public Node(T data) {
            this.data = data;
        }
    }
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    class BTreePrinter {
    
        public static <T extends Comparable<?>> void printNode(Node<T> root) {
            int maxLevel = BTreePrinter.maxLevel(root);
    
            printNodeInternal(Collections.singletonList(root), 1, maxLevel);
        }
    
        private static <T extends Comparable<?>> void printNodeInternal(
                List<Node<T>> nodes, int level, int maxLevel) {
            if (nodes.isEmpty() || BTreePrinter.isAllElementsNull(nodes))
                return;
    
            int floor = maxLevel - level;
            int endgeLines = (int) Math.pow(2, (Math.max(floor - 1, 0)));
            int firstSpaces = (int) Math.pow(2, (floor)) - 1;
            int betweenSpaces = (int) Math.pow(2, (floor + 1)) - 1;
    
            BTreePrinter.printWhitespaces(firstSpaces);
    
            List<Node<T>> newNodes = new ArrayList<Node<T>>();
            for (Node<T> node : nodes) {
                if (node != null) {
                    String nodeData = String.valueOf(node.data);
                    if (nodeData != null) {
                        if (nodeData.length() == 1) {
                            nodeData = "0" + nodeData;
                        }
                    }
                    System.out.print(nodeData);
                    newNodes.add(node.left);
                    newNodes.add(node.right);
                } else {
                    newNodes.add(null);
                    newNodes.add(null);
                    System.out.print("  ");
                }
    
                BTreePrinter.printWhitespaces(betweenSpaces);
            }
            System.out.println("");
    
            for (int i = 1; i <= endgeLines; i++) {
                for (int j = 0; j < nodes.size(); j++) {
                    BTreePrinter.printWhitespaces(firstSpaces - i);
                    if (nodes.get(j) == null) {
                        BTreePrinter.printWhitespaces(endgeLines + endgeLines + i
                                + 1);
                        continue;
                    }
    
                    if (nodes.get(j).left != null)
                        System.out.print("//");
                    else
                        BTreePrinter.printWhitespaces(1);
    
                    BTreePrinter.printWhitespaces(i + i - 1);
    
                    if (nodes.get(j).right != null)
                        System.out.print("\\\\");
                    else
                        BTreePrinter.printWhitespaces(1);
    
                    BTreePrinter.printWhitespaces(endgeLines + endgeLines - i);
                }
    
                System.out.println("");
            }
    
            printNodeInternal(newNodes, level + 1, maxLevel);
        }
    
        private static void printWhitespaces(int count) {
            for (int i = 0; i < 2 * count; i++)
                System.out.print(" ");
        }
    
        private static <T extends Comparable<?>> int maxLevel(Node<T> node) {
            if (node == null)
                return 0;
    
            return Math.max(BTreePrinter.maxLevel(node.left),
                    BTreePrinter.maxLevel(node.right)) + 1;
        }
    
        private static <T> boolean isAllElementsNull(List<T> list) {
            for (Object object : list) {
                if (object != null)
                    return false;
            }
    
            return true;
        }
    
    }
    

    Please note that BTreePrinter is a code I took somewhere in Stackoverflow long back and I modified to use with 2 digit numbers.It will be broken if we move to 3 digit numbers and it is only for simple understanding of how the Heap structure looks.A fix for 3 digit numbers is to keep everything as multiple of 3. Also due credits to Sesh Venugopal for wonderful tutorial on Youtube on Heap data structure

    0 讨论(0)
提交回复
热议问题