【问题标题】:How to implement a maximum priority queue using a heap-ordered binary tree with a triply-linked Node?如何使用具有三重链接节点的堆排序二叉树实现最大优先级队列?
【发布时间】:2020-06-28 19:54:06
【问题描述】:

我正在尝试使用具有三重链接节点的堆二叉树来实现最大优先级队列。这是我目前在运行它并尝试打印出树时所拥有的代码,没有打印出它只是空行。我正在使用帮助方法 sink 和 Swim 来帮助我在添加不同元素时组织队列。我还在实现一个 ADT (MaxPQ),它只有需要实现的公共方法。我想知道我是否做错了什么?

public class LinkedMaxPQ<T extends Comparable<T>> implements MaxPQ<T> {

  // Instance variables
  Node root;
  int size;
  Node lastInserted;

  // Node inner class definition

  // Node class
  class Node {
    int N;
    T info;
    Node left;
    Node right;
    Node parent;

    Node(T info, int N) {
      this.info = info; this.N = N;
    }
  }

  private void swim(Node x){
    if(x == null) return;
    if(x.parent == null) return; // we're at root
    int cmp = x.info.compareTo(x.parent.info);
    if(cmp > 0){
      swapNodeData(x, x.parent);
      swim(x.parent);
    }
  }
  private void swapNodeData(Node x, Node y){
    T temp = x.info;
    x.info = y.info;
    y.info = temp;
  }
  private void sink(Node x){
    if(x == null) return;
    Node swapNode;
    if(x.left == null && x.right == null){
      return;
    }
    else if(x.left == null){
      swapNode = x.right;
      int cmp = x.info.compareTo(swapNode.info);
      if(cmp < 0)
      swapNodeData(swapNode, x);
    } else if(x.right == null){
      swapNode = x.left;
      int cmp = x.info.compareTo(swapNode.info);
      if(cmp < 0)
      swapNodeData(swapNode, x);
    } else{
      int cmp = x.left.info.compareTo(x.right.info);
      if(cmp >= 0){
        swapNode = x.left;
      } else{
        swapNode = x.right;
      }
      int cmpParChild = x.info.compareTo(swapNode.info);
      if(cmpParChild < 0) {
        swapNodeData(swapNode, x);
        sink(swapNode);
      }
    }
  }
  String printThisLevel (Node rootnode, int level) {
    StringBuilder s = new StringBuilder();

    // Base case 1: if the current rootnode is null, return the current string.
    if (rootnode == null) {
      return s.toString();
    }

    // Base case 2: If you're at the first level, append the
    // info field of the current rootnode.
    if (level == 1) {
      s.append( rootnode.info.toString());
    }
    // Recursive calls: otherwise call the method on the left
    // and on the right of the next lower level.
    else if (level > 1)  {
      s.append( printThisLevel(rootnode.left, level-1));
      s.append( printThisLevel(rootnode.right, level-1));
    }
    return s.toString();
  }

  private int size(Node x){
    if(x == null) return 0;
    return x.N;
  }

  private Node insert(Node x, T data){
    if(x == null){
      lastInserted = new Node(data, 1);
      return lastInserted;
    }
    // compare left and right sizes see where to go
    int leftSize = size(x.left);
    int rightSize = size(x.right);

    if(leftSize <= rightSize){
      // go to left
      Node inserted = insert(x.left, data);
      x.left = inserted;
      inserted.parent = x;
    } else{
      // go to right
      Node inserted = insert(x.right, data);
      x.right = inserted;
      inserted.parent = x;
    }
    x.N = size(x.left) + size(x.right) + 1;
    return x;
  }
  private Node resetLastInserted(Node x){
    if(x == null) return null;
    if(x.left == null && x.right == null) return x;
    if(size(x.right) < size(x.left))return resetLastInserted(x.left);
    else                            return resetLastInserted(x.right);
  }

  public void insert(T data){
    root = insert(root, data);
    swim(lastInserted);
  }
  public T getMax(){
    if(root == null) return null;
    return root.info;
  }
  public T removeMax(){
    if(size() == 1){
      T ret = root.info;
      root = null;
      return ret;
    }
    swapNodeData(root, lastInserted);
    Node lastInsParent = lastInserted.parent;
    T lastInsData = lastInserted.info;
    if(lastInserted == lastInsParent.left){
      lastInsParent.left = null;
    } else{
      lastInsParent.right = null;
    }

    Node traverser = lastInserted;

    while(traverser != null){
      traverser.N--;
      traverser = traverser.parent;
    }

    lastInserted = resetLastInserted(root);

    sink(root);

    return lastInsData;
  }
  public int size(){
    return size(root);
  }
  public boolean isEmpty(){
    return size() == 0;
  }


  public String toString() {
    // Create a StringBuilder object to make it more efficient.
    StringBuilder sb=new StringBuilder();

    // get the height of the tree
    int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));

    // for each level in the tree, call printThisLevel and
    // append the output to the StringBuilder
    for (int i=1; i<=height; i++) {
      sb.append("level " + i + ": "+ printThisLevel(this.root, i) + "\n");
    }

    // Return the string of the StringBuilder object
    return sb.toString();
  }


  public static void main (String[] args) {
    LinkedMaxPQ<String> t = new LinkedMaxPQ<String>();
    t.insert("a");
    System.out.println(t.toString());
    t.insert("b");
    t.insert("c");
    t.insert("d");
    t.insert("e");
    t.insert("f");
    t.insert("g");
    t.insert("h");
    t.insert("i");
    t.insert("j");
    t.insert("k");
    t.size();
    t.removeMax();
    t.getMax();
    t.removeMax();
    t.insert("x");
    t.insert("y");
    t.removeMax();
    t.getMax();
    System.out.println(t.toString());

  }

}

【问题讨论】:

  • 您的调试工作取得了哪些成果?
  • @sparkyShorts 到目前为止我发现插入函数似乎没有向树中插入任何东西我无法判断这是由于插入函数还是 toString()方法。

标签: java linked-list binary-tree nodes


【解决方案1】:

在这一行:

int height = (int)Math.ceil(Math.log(size+1) / Math.log(2));

size 应该是 size()。

int height = (int)Math.ceil(Math.log(size()+1) / Math.log(2));

经过这次修正,结果出来了。 但是,有一个逻辑问题,需要解决。 对于测试用例,testdata = new int[] {3, 5, 2, -7, 9, 4, 7}; 结果是 9 4 7 -7 3 2 5 但正确的结果应该是 9 5 7 -7 3 2 4 (来自另一个数组实现)。 我知道错误来自在第 3 级插入数据 {9},其父级应该是左侧的第 2 级数据 {3},而不是右侧的 {2}。有什么办法解决吗?

【讨论】:

  • 另外,任何人都知道如何为以下结果执行 toString:9(5(-7, 3), 7(2, 4))?
猜你喜欢
  • 2013-11-30
  • 2017-02-08
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
相关资源
最近更新 更多