Java实现链式结构大根堆(MaxHeap)并打包运行

堆相关知识复习(y总版)

我们本次预计使用Java来实现一个链式的大根堆,支持插入节点,修改节点值,堆排序,打印堆结构等功能。并将项目打包为jar包在cmd控制台运行。

1.功能设计

大根堆是一个完全二叉树,每个父节点的值大于两个子节点的值,那么要实现插入节点的操作,我们就需要知道从根节点插入所要经过的路径,以在节点5插入为例:
cr0.jpg

5的二进制表示为101,第一个1代表从根节点1开始,第二个0表示向左儿子走,第三个1表示向右儿子走,最终走到了节点5这里。这个找到插入节点路径的函数用getPath(x)实现。
数据结构设计

我们的每个堆中包括一个堆容 s i z siz siz堆二叉树 ∗ ∗ h e a d **head head数组 s o r t e d A r r a y sortedArray sortedArray用于存储堆排序结果
每个堆二叉树节点包括
节点值** v a l val val左右儿子编号 l e f t left left r i g h t right right父亲节点编号 f a fa fa
为了能够较为直观地打印出树,编写一个DefaultBinaryTreeNodePrinterDefaultBinaryTreePrinter类用于树的打印。

堆排序,操作简单来讲就是将堆顶的元素拿出来,之后找到堆最后的一个元素的值 g e t P a t h ( 堆的大小 ) getPath(堆的大小) getPath(堆的大小),用其替换堆顶元素的值,之后从堆顶开始执行下沉操作 d o w n ( ) down() down(),同时堆大小 s i z − 1 siz-1 siz1,循环往复直到堆大小siz=0。

将排序好的结果存入数组 s o r t e d A r r a y sortedArray sortedArray

我们的堆支持一下几种操作:
  • 0: 堆初始化
  • 1: 堆中插入一个元素
  • 2: 修改堆节点v的元素值为k
  • 3: 堆排序操作
  • 4: 打印堆的树结构
  • 5: 打印堆排序结果
  • 6: 输入一个数组构建堆
  • 9: 退出程序

2.代码实现

先上C++代码(没有操作6和画树操作):

#include<bits/stdc++.h>
using namespace std;
struct node{
    int val;
    node *left;
    node *right;
    node *fa;

    node(int x): val(x),left(NULL),right(NULL),fa(NULL) {};
    node(int x,node *fa):val(x),left(NULL),right(NULL),fa(fa) {};
};
struct Heap{
    int siz;
    node *head;
    vector<int> sortedArray;
    
    string getPath(int t)
    {
        string s="";
        while(t!=1)
        {
            int k=t%2;
            s=(char)(k+'0')+s;
            t/=2;
        }
        return s;
    }
    
    
    void up(node *root,string s,int idx)
    {
        if(idx==s.size()){
            if(root->val>root->fa->val)
            {
                swap(root->val,root->fa->val);
            }   
            return ;
        } 
        if(s[idx]=='1'){
            up(root->right,s,idx+1); 
            if(root->fa){
                if(root->val>root->fa->val) swap(root->val,root->fa->val);
            }
        }
        else{
            up(root->left,s,idx+1);
            if(root->fa){
                if(root->val>root->fa->val) swap(root->val,root->fa->val);
            }
        }
        
    }

    void insert(int x){
        if(!siz){
            head=new node(x);
            siz++;
        }
        else{
            string s=getPath(siz+1);
            head=insert(head,NULL,s,0,x);
            siz++;
            s=getPath(siz);
            up(head,s,0);
        }
    }
    
    node* insert(node *root,node *pre,string s,int idx,int x)
    {
        if(!root){
            return new node(x,pre);
        } 
        if(s[idx]=='1'){
            root->right=insert(root->right,root,s,idx+1,x);   
        }
        else{
            root->left=insert(root->left,root,s,idx+1,x);
        }
        return root;
    }

    node* modify(node *root,string s,int idx,int x)
    {
        if(idx==s.size()){
            if(x < root->val){
                puts("Value k < key value!");
                return root;
            }
            
            root->val=x;
            return root;                 
        } 
        if(s[idx]=='1'){
            root->right=modify(root->right,s,idx+1,x);   
        }
        else{
            root->left=modify(root->left,s,idx+1,x);
        }
        return root;
    }
    
    void increaseKey(int v,int k)
    {
        if(v>siz)
        {
            puts("Node v not exist!");
            return ;
        }
        else{
            string s=getPath(v);
            head=modify(head,s,0,k);
            down(v,head,siz);
            up(head,s,0);
        }
        
    }
    
    node *copyHeap(node *a,node *b)
    {
        if(b)
            a=new node(b->val,b->fa);
        else 
            return NULL;
        a->left=copyHeap(a->left,b->left);
        a->right=copyHeap(a->right,b->right);
        return a;
    }
    
    int query(node *root,string s,int idx)
    {
        if(idx==s.size()){
            return root->val;                 
        } 
        
        if(s[idx]=='1'){
            return query(root->right,s,idx+1);   
        }
        else{
            return query(root->left,s,idx+1);
        }
    }
    
    node *queryNode(node *root,string s,int idx)
    {
        if(idx==s.size()){
            return root;                 
        } 
        
        if(s[idx]=='1'){
            return queryNode(root->right,s,idx+1);   
        }
        else{
            return queryNode(root->left,s,idx+1);
        }
    }
    //下沉操作
    void down(int x,node *root,int len)
    {
        //找到左右儿子中最大的数,替换父亲节点的值
        int t=x;
        if(x*2<=len && query(root,getPath(2*x),0)>query(root,getPath(t),0)) t=2*x;
        if(x*2+1<=len && query(root,getPath(2*x+1),0)>query(root,getPath(t),0)) t=2*x+1;
        if(x!=t)
        {
            node *a=queryNode(root,getPath(x),0);
            node *b=queryNode(root,getPath(t),0);
            swap(a->val,b->val);
            down(t,root,len);
        }
        
    }
    
    void output(node *root)
    {
        queue<node*> q;
        q.push(root);
        while(q.size())
        {
            int len=q.size();
            for(int i=0;i<len;i++)
            {
                auto t=q.front(); q.pop();
                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
                cout<<t->val<<" ";
            }
            puts("");
        }
    }
    
    void outputSortResult()
    {
        reverse(sortedArray.begin(),sortedArray.end());
        for(auto x:sortedArray) cout<<x<<" ";
        puts("");
    }
    
    void heapSort(Heap hp)
    {
        sortedArray.clear();
        Heap temp;
        temp.siz=hp.siz;
        temp.head=copyHeap(temp.head,hp.head);
        queue<node*> q;
        q.push(temp.head);
        //output(temp.head);
        for(int i=0;i<siz;i++)
        {
            sortedArray.push_back(temp.head->val);
            string s=getPath(temp.siz--);
            temp.head->val=query(temp.head,s,0);
            //int val=query(siz)->val;
            //cout<<temp.head->val<<endl;
            down(1,temp.head,temp.siz);
            //output(temp.head);
        }
    
    }

    Heap():siz(0){}
    
};
int main()
{
    Heap h;
    h.insert(5);
    h.insert(6);
    h.insert(7);
    h.insert(1);
    h.insert(2);
    h.increaseKey(4,10);
    h.output(h.head);
    h.heapSort(h);
    h.outputSortResult();
    h.insert(15);
    h.insert(25);
    h.insert(36);
    h.heapSort(h);
    h.outputSortResult();
    
    return 0;
}

Java代码

MaxHeap.java

package com.joy187.re8joymod;

import java.util.*;

//定义二叉树节点
class node{
    int val;
    node left;
    node right;
    node fa;

    node(int x){
        this.val=x;
        this.left=null;
        this.right=null;
        this.fa=null;
    }
    node(int x,node fa){
        this.val=x;
        this.left=null;
        this.right=null;
        this.fa=fa;
    }
};

//定义我们的堆
class Heap{
    int siz;
    node head;
    List<Integer> sortedArray=new ArrayList<Integer>();

    Heap(){
        this.siz=0;
        this.head=null;
    }

    void init()
    {
        this.siz=0;
        this.head=null;
        this.sortedArray.clear();
    }

    void swap(node a,node b)
    {
        int temp=a.val;
        a.val=b.val;
        b.val=temp;
    }

    //find a path to the position of the new node
    String getPath(int t)
    {
        String s="";
        while(t!=1)
        {
            int k=t%2;
            s=(char)(k+'0')+s;
            t/=2;
        }
        return s;
    }

    //place the new node in the right place of the heap
    void up(node root,String s,int idx)
    {
        if(idx==s.length()){
            if(root.val > root.fa.val)
            {
                //int temp=root.val;
                //root.val=root.fa.val;
                //root.fa.val=temp;
                swap(root,root.fa);
            }
            return ;
        }
        if(s.charAt(idx)=='1'){
            up(root.right,s,idx+1);
            if(root.fa!=null){
                if(root.val > root.fa.val) swap(root,root.fa);
            }
        }
        else{
            up(root.left,s,idx+1);
            if(root.fa!=null){
                if(root.val > root.fa.val) swap(root,root.fa);
            }
        }

    }

    //insert a node to the binary tree heap
    node insert(node root,node pre,String s,int idx,int x)
    {
        if(root==null){
            return new node(x,pre);
        }
        if(s.charAt(idx)=='1'){
            root.right=insert(root.right,root,s,idx+1,x);
        }
        else{
            root.left=insert(root.left,root,s,idx+1,x);
        }
        return root;
    }

    //insert a node to the binary tree heap
    void insert(int x) {
        if (this.siz == 0) {
            this.head = new node(x);
            this.siz++;
        } else {
            String s = getPath(this.siz + 1);
            this.head = insert(this.head, null, s, 0, x);
            this.siz++;
            s = getPath(this.siz);
            up(this.head, s, 0);
        }
    }
    //modify the vertex v with new key valule x
    node modify(node root,String s,int idx,int x)
    {
        if(idx==s.length()){
            if(x < root.val){
                System.out.println("Value k < key value!");
                return root;
            }

            root.val=x;
            return root;
        }
        if(s.charAt(idx)=='1'){
            root.right=modify(root.right,s,idx+1,x);
        }
        else{
            root.left=modify(root.left,s,idx+1,x);
        }
        return root;
    }

    //assigns to vertex v the new key value k.
    void increaseKey(int v,int k)
    {
        if(v>this.siz)
        {
            System.out.println("Node v not exist!");
            return ;
        }
        else{
            String s=getPath(v);
            this.head=modify(this.head,s,0,k);
            up(this.head,s,0);
        }
    }

    void output(node root)
    {
//        Queue<node> q=new LinkedList();
//        q.add(root);
//        while(q.size()>0)
//        {
//            int len=q.size();
//            for(int i=0;i<len;i++)
//            {
//                node t=q.poll();
//                if(t.left!=null) q.offer(t.left);
//                if(t.right!=null) q.offer(t.right);
//                //if(t->fa) cout<<t->fa->val<<" ";
//                System.out.print(t.val+" ");
//            }
//            System.out.println("");
//        }
    }

    void outputSortResult()
    {
        for(int i=siz-1;i>=0;i--)
            System.out.print(sortedArray.get(i)+" ");
        System.out.println("");
    }

    node copyHeap(node a,node b)
    {
        if(b!=null)
            a=new node(b.val,b.fa);
        else
            return null;
        a.left=copyHeap(a.left,b.left);
        a.right=copyHeap(a.right,b.right);
        return a;
    }

    int query(node root,String s,int idx)
    {
        if(idx==s.length()){
            return root.val;
        }

        if(s.charAt(idx)=='1'){
            return query(root.right,s,idx+1);
        }
        else{
            return query(root.left,s,idx+1);
        }
    }

    node queryNode(node root,String s,int idx)
    {
        if(idx==s.length()){
            return root;
        }

        if(s.charAt(idx)=='1'){
            return queryNode(root.right,s,idx+1);
        }
        else{
            return queryNode(root.left,s,idx+1);
        }
    }

    void down(int x,node root,int len)
    {
        int t=x;
        if(x*2<=len && query(root,getPath(2*x),0) > query(root,getPath(t),0)) t=2*x;
        if(x*2+1<=len && query(root,getPath(2*x+1),0) > query(root,getPath(t),0)) t=2*x+1;
        if(x!=t)
        {
            node a=queryNode(root,getPath(x),0);
            node b=queryNode(root,getPath(t),0);
            swap(a,b);
            down(t,root,len);
        }

    }

    void heapSort(Heap hp)
    {
        this.sortedArray.clear();
        Heap temp=new Heap();
        temp.siz=hp.siz;
        temp.head=copyHeap(temp.head,hp.head);

        for(int i=0;i<siz;i++)
        {
            sortedArray.add(temp.head.val);
            String s=getPath(temp.siz--);
            temp.head.val=query(temp.head,s,0);
            //int val=query(siz)->val;
            //cout<<temp.head->val<<endl;
            down(1,temp.head,temp.siz);
            //output(temp.head);
        }
    }

    //use an array to build a heap
    void arrayBuildHeap(Heap h,List<Integer> v)
    {
        h.head=null;
        h.siz=0;
        for(int i=0;i<v.size();i++)
        {
           insert(v.get(i));
        }

    }

};
//定义树节点的绘画类
class DefaultBinaryTreeNodePrinter<T> {

    /**
     * The default top padding.
     */
    private static final int DEFAULT_TOP_PADDING = 0;

    /**
     * The default right padding.
     */
    private static final int DEFAULT_RIGHT_PADDING = 0;

    /**
     * The default bottom padding.
     */
    private static final int DEFAULT_BOTTOM_PADDING = 0;

    /**
     * The default left padding.
     */
    private static final int DEFAULT_LEFT_PADDING = 0;

    /**
     * The default character used to print node corners.
     */
    private static final char DEFAULT_CORNER_CHARACTER = '+';

    /**
     * The default character used to print horizontal node borders.
     */
    private static final char DEFAULT_HORIZONTAL_BORDER_CHARACTER = '-';

    /**
     * The default character used to print vertical node borders.
     */
    private static final char DEFAULT_VERTICAL_BORDER_CHARACTER = '|';

    /**
     * The top padding.
     */
    private int paddingTop = DEFAULT_TOP_PADDING;

    /**
     * The right padding.
     */
    private int paddingRight = DEFAULT_RIGHT_PADDING;

    /**
     * The bottom padding.
     */
    private int paddingBottom = DEFAULT_BOTTOM_PADDING;

    /**
     * The left padding.
     */
    private int paddingLeft = DEFAULT_LEFT_PADDING;

    /**
     * The character used to represent top left corners.
     */
    private char topLeftCornerCharacter = DEFAULT_CORNER_CHARACTER;

    /**
     * The character used to represent top right corners.
     */
    private char topRightCornerCharacter = DEFAULT_CORNER_CHARACTER;

    /**
     * The character used to represent bottom left corners.
     */
    private char bottomLeftCornerCharacter = DEFAULT_CORNER_CHARACTER;

    /**
     * The character used to represent bottom right corners.
     */
    private char bottomRightCornerCharacter = DEFAULT_CORNER_CHARACTER;

    /**
     * The character used to print the top border.
     */
    private char topBorderCharacter = DEFAULT_HORIZONTAL_BORDER_CHARACTER;

    /**
     * The character used to print the right border.
     */
    private char rightBorderCharacter = DEFAULT_VERTICAL_BORDER_CHARACTER;

    /**
     * The character used to print the bottom border.
     */
    private char bottomBorderCharacter = DEFAULT_HORIZONTAL_BORDER_CHARACTER;

    /**
     * The character used to print the left border.
     */
    private char leftBorderCharacter = DEFAULT_VERTICAL_BORDER_CHARACTER;

    public TextSprite print(node Node) {
        String value = String.valueOf(Node.val);
        String[] lines = value.split("\n");
        int maximumLineLength = getMaximumLineLength(lines);
        int width = 2 + paddingLeft + paddingRight + maximumLineLength;
        int height = 2 + paddingTop + paddingBottom + lines.length;
        TextSprite textSprite = new TextSprite(width, height);
        printCorners(textSprite);
        printBorders(textSprite);
        printLines(textSprite, lines);
        Utils.setEmptyTextSpriteCellsToSpace(textSprite);
        return textSprite;
    }

    public int getTopPadding() {
        return paddingTop;
    }

    public int getRightPadding() {
        return paddingRight;
    }

    public int getBottomPadding() {
        return paddingBottom;
    }

    public int getLeftPadding() {
        return paddingLeft;
    }

    public char getTopLeftCornerCharacter() {
        return topLeftCornerCharacter;
    }

    public char getTopRightCornerCharacter() {
        return topRightCornerCharacter;
    }

    public char getBottomLeftCornerCharacter() {
        return bottomLeftCornerCharacter;
    }

    public char getBottomRightCornerCharacter() {
        return bottomRightCornerCharacter;
    }

    public char getTopBorderCharacter() {
        return topBorderCharacter;
    }

    public char getRightBorderCharacter() {
        return rightBorderCharacter;
    }

    public char getBottomBorderCharacter() {
        return bottomBorderCharacter;
    }

    public char getLeftBorderCharacter() {
        return leftBorderCharacter;
    }

    public void setTopPadding(int paddingTop) {
        this.paddingTop = checkPaddingTop(paddingTop);
    }

    public void setRightPadding(int paddingRight) {
        this.paddingRight = checkPaddingRight(paddingRight);
    }

    public void setBottomPadding(int paddingBottom) {
        this.paddingBottom = checkPaddingBottom(paddingBottom);
    }

    public void setLeftPadding(int paddingLeft) {
        this.paddingLeft = checkPaddingLeft(paddingLeft);
    }

    public void setTopLeftCornerCharacter(char c) {
        topLeftCornerCharacter = c;
    }

    public void setTopRightCornerCharacter(char c) {
        topRightCornerCharacter = c;
    }

    public void setBottomLeftCornerCharacter(char c) {
        bottomLeftCornerCharacter = c;
    }

    public void setBottomRightCornerCharacter(char c) {
        bottomRightCornerCharacter = c;
    }

    public void setTopBorderCharacter(char c) {
        topBorderCharacter = c;
    }

    public void setRightBorderCharacter(char c) {
        rightBorderCharacter = c;
    }

    public void setBottomBorderCharacter(char c) {
        bottomBorderCharacter = c;
    }

    public void setLeftBorderCharacter(char c) {
        leftBorderCharacter = c;
    }

    private int checkPadding(int padding, String errorMessage) {
        if (padding < 0) {
            throw new IllegalArgumentException(
                    errorMessage + ": the given padding is negative: " +
                            padding + ". Must be at least 0!");
        }

        return padding;
    }

    private int checkPaddingTop(int padding) {
        return checkPadding(padding, "Top padding is invalid");
    }

    private int checkPaddingRight(int padding) {
        return  checkPadding(padding, "Right padding is invalid");
    }

    private int checkPaddingBottom(int padding) {
        return checkPadding(padding, "Bottom padding is invalid");
    }

    private int checkPaddingLeft(int padding) {
        return checkPadding(padding, "Left padding is invalid");
    }

    private int getMaximumLineLength(String[] lines) {
        int maximumLineLength = 0;

        for (String line : lines) {
            maximumLineLength = Math.max(maximumLineLength, line.length());
        }

        return maximumLineLength;
    }

    private void printCorners(TextSprite textSprite) {
        int width = textSprite.getWidth();
        int height = textSprite.getHeight();
        textSprite.setChar(0, 0, topLeftCornerCharacter);
        textSprite.setChar(width - 1, 0, topRightCornerCharacter);
        textSprite.setChar(0, height - 1, bottomLeftCornerCharacter);
        textSprite.setChar(width - 1, height - 1, bottomRightCornerCharacter);
    }

    private void printBorders(TextSprite textSprite) {
        int width = textSprite.getWidth();
        int height = textSprite.getHeight();

        for (int x = 1; x < width - 1; ++x) {
            textSprite.setChar(x, 0, topBorderCharacter);
            textSprite.setChar(x, height - 1, bottomBorderCharacter);
        }

        for (int y = 1; y < height - 1; ++y) {
            textSprite.setChar(0, y, leftBorderCharacter);
            textSprite.setChar(width - 1, y, rightBorderCharacter);
        }
    }

    private void printLines(TextSprite textSprite, String[] lines) {
        int startY = 1 + paddingTop;
        int startX = 1 + paddingLeft;

        for (int y = 0; y < lines.length; ++y) {
            char[] chars = lines[y].toCharArray();

            for (int x = 0; x < chars.length; ++x) {
                textSprite.setChar(startX + x, startY + y, chars[x]);
            }
        }
    }
}
class TextSprite {

    /**
     * The minimum width of a sprite in characters.
     */
    private static final int MINIMUM_SPRITE_WIDTH = 1;

    /**
     * The minimum height of a sprite in characters.
     */
    private static final int MINIMUM_SPRITE_HEIGHT = 1;

    /**
     * The width of this text sprite.
     */
    private final int width;

    /**
     * The height of this text sprite.
     */
    private final int height;

    /**
     * Contains all the characters.
     */
    private final char[][] window;

    /**
     * Constructs a new empty text sprite.
     *
     * @param spriteWidth  the number of text columns.
     * @param spriteHeight the number of text rows.
     */
    public TextSprite(int spriteWidth, int spriteHeight) {
        this.width = checkWidth(spriteWidth);
        this.height = checkHeight(spriteHeight);
        this.window = new char[spriteHeight*3][spriteWidth*3];
    }

    /**
     * Sets a particular cell to {@code c}.
     *
     * @param x the x-coordinate of the cell.
     * @param y the y-coordinate of the cell.
     * @param c the character to set.
     */
    public void setChar(int x, int y, char c) {
        checkX(x);
        checkY(y);
        window[y][x] = c;
    }

    /**
     * Reads the content of a particular cell.
     *
     * @param x the x-coordinate of the cell.
     * @param y the y-coordinate of the cell.
     * @return the contents of the cell.
     */
    public char getChar(int x, int y) {
        checkX(x);
        checkY(y);
        return window[y][x];
    }

    /**
     * Returns the number of columns in this sprite.
     *
     * @return the number of columns.
     */
    public int getWidth() {
        return width;
    }

    /**
     * Returns the number of rows in this sprite.
     *
     * @return the number of rows.
     */
    public int getHeight() {
        return height;
    }

    /**
     * Applies the input text sprite on top of a rectangle of this text sprite.
     *
     * @param textSprite the text sprite to apply.
     * @param xOffset    the horizontal offset from the left border.
     * @param yOffset    the vertical offset from the top border.
     */
    public void apply(TextSprite textSprite, int xOffset, int yOffset) {
        Objects.requireNonNull(textSprite, "The input TextSprite is null!");

        if (xOffset < 0) {
            throw new IndexOutOfBoundsException("xOffset (" + xOffset + ") " +
                    "may not be negative!");
        }

        if (yOffset < 0) {
            throw new IndexOutOfBoundsException("yOffset (" + yOffset + ") " +
                    "may not be negative!");
        }

        if (xOffset + textSprite.getWidth() > getWidth()) {
            throw new IndexOutOfBoundsException("xOffset (" + xOffset + ") " +
                    "is too large! Must be at most " +
                    (getWidth() - textSprite.getWidth()) + ".");
        }

        if (yOffset + textSprite.getHeight() > getHeight()) {
            throw new IndexOutOfBoundsException("yOffset (" + yOffset + ") " +
                    "is too large! Must be at most " +
                    (getHeight() - textSprite.getHeight()) + ".");
        }

        for (int y = 0; y < textSprite.getHeight(); ++y) {
            for (int x = 0; x < textSprite.getWidth(); ++x) {
                setChar(xOffset + x, yOffset + y, textSprite.getChar(x, y));
            }
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder((width + 1) * height - 1);
        String separator = "";

        for (int y = 0; y < height; ++y) {
            sb.append(separator);
            separator = "\n";

            for (int x = 0; x < width; ++x) {
                sb.append(getChar(x, y));
            }
        }

        return sb.toString();
    }

    private int checkWidth(int width) {
        if (width < MINIMUM_SPRITE_WIDTH) {
            throw new IllegalArgumentException(
                    "The sprite width is too small (" + width + "). " +
                            "Must be at least " + MINIMUM_SPRITE_WIDTH + ".");
        }

        return width;
    }

    private int checkHeight(int height) {
        if (height < MINIMUM_SPRITE_HEIGHT) {
            throw new IllegalArgumentException(
                    "The sprite height is too small (" + height + "). " +
                            "Must be at least " + MINIMUM_SPRITE_HEIGHT + ".");
        }

        return height;
    }

    private void checkX(int x) {
        if (x < 0) {
            throw new IndexOutOfBoundsException("x = " + x + " is negative.");
        } else if (x >= width) {
            throw new IndexOutOfBoundsException("x = " + x + " exceeds the " +
                    "width = " + width);
        }
    }

    private void checkY(int y) {
        if (y < 0) {
            throw new IndexOutOfBoundsException("y = " + y + " is negative.");
        } else if (y >= height) {
            throw new IndexOutOfBoundsException("y = " + y + " exceeds the " +
                    "height = " + height);
        }
    }
};
//二叉树打印
class DefaultBinaryTreePrinter<T>  {

    /**
     * When combining the text sprites of two sibling subtrees, by default, at
     * least one character worth horizontal space will be put between the two
     * sprites.
     */
    private static final int DEFAULT_MINIMUM_SIBLING_SPACE = 1;

    /**
     * The default character for printing arrow tips.
     */
    private static final char DEFAULT_ARROW_TIP_CHARACTER = 'V';

    /**
     * The minimum number of spaces between two siblings.
     */
    private int siblingSpace = DEFAULT_MINIMUM_SIBLING_SPACE;

    /**
     * The arrow tip character.
     */
    private char arrowTipCharacter = DEFAULT_ARROW_TIP_CHARACTER;

    public String print(node root, DefaultBinaryTreeNodePrinter<T> nodePrinter) {
        if (root == null) {
            return "null";
        }

        TextSprite textSprite = printImpl(root, nodePrinter).textSprite;
        Utils.setEmptyTextSpriteCellsToSpace(textSprite);
        return textSprite.toString();
    }

    public int getSiblingSpace() {
        return siblingSpace;
    }

    public char getArrowTipCharacter() {
        return arrowTipCharacter;
    }

    public void setSiblingSpace(int siblingSpace) {
        this.siblingSpace = checkSiblingSpace(siblingSpace);
    }

    public void setArrowTipCharacter(char arrowTipCharacter) {
        this.arrowTipCharacter = arrowTipCharacter;
    }

    private static final class SubtreeDescriptor {

        TextSprite textSprite;
        int rootNodeOffset;
        int rootNodeWidth;
    }

    private SubtreeDescriptor printImpl(node node,DefaultBinaryTreeNodePrinter<T> nodePrinter) {
        if (node.left == null && node.right == null) {
            TextSprite leafNodeTextSprite = nodePrinter.print(node);
            SubtreeDescriptor subtreeDescriptor = new SubtreeDescriptor();
            subtreeDescriptor.rootNodeOffset = 0;
            subtreeDescriptor.rootNodeWidth = leafNodeTextSprite.getWidth();
            subtreeDescriptor.textSprite = leafNodeTextSprite;
            return subtreeDescriptor;
        }

        if (node.left != null && node.right != null) {
            return printWithTwoChildrenImpl(node, nodePrinter);
        }

        if (node.left != null) {
            return printWithLeftChildImpl(node, nodePrinter);
        }

        return printWithRightChildImpl(node, nodePrinter);
    }

    private SubtreeDescriptor printWithTwoChildrenImpl(node node, DefaultBinaryTreeNodePrinter<T> nodePrinter) {
        SubtreeDescriptor subtreeDescriptor = new SubtreeDescriptor();
        SubtreeDescriptor leftChildDescriptor = printImpl(node.left, nodePrinter);
        SubtreeDescriptor rightChildDescriptor = printImpl(node.right, nodePrinter);

        TextSprite nodeTextSprite = nodePrinter.print(node);
        TextSprite leftChildTextSprite = leftChildDescriptor.textSprite;
        TextSprite rightChildTextSprite = rightChildDescriptor.textSprite;

        // The height of the resulting text sprite.
        int subtreeTextSpriteHeight = 1 + nodeTextSprite.getHeight() +
                Math.max(leftChildTextSprite.getHeight(),
                        rightChildTextSprite.getHeight());

        int aLeft = (nodeTextSprite.getWidth() - siblingSpace) / 2;
        int aRight = nodeTextSprite.getWidth() - siblingSpace - aLeft;

        int bLeft = leftChildTextSprite.getWidth() -
                leftChildDescriptor.rootNodeOffset -
                leftChildDescriptor.rootNodeWidth;

        int leftPartOffset = 0;

        if (aLeft + 2 > bLeft + leftChildDescriptor.rootNodeWidth) {
            leftPartOffset = aLeft + 2
                    - bLeft
                    - leftChildDescriptor.rootNodeWidth;
        }

        int rightPartOffset = 0;

        if (rightChildDescriptor.rootNodeOffset +
                rightChildDescriptor.rootNodeWidth < aRight + 2) {
            rightPartOffset = aRight + 2 - rightChildDescriptor.rootNodeOffset
                    - rightChildDescriptor.rootNodeWidth;
        }

        // The width of the resulting text sprite.
        int subtreeTextSpriteWidth =
                leftChildTextSprite.getWidth() +
                        leftPartOffset +
                        siblingSpace +
                        rightPartOffset +
                        rightChildTextSprite.getWidth();

        TextSprite subtreeTextSprite = new TextSprite(subtreeTextSpriteWidth,
                subtreeTextSpriteHeight);

        subtreeTextSprite.apply(leftChildTextSprite,
                0,
                nodeTextSprite.getHeight() + 1);

        subtreeTextSprite.apply(rightChildTextSprite,
                leftChildTextSprite.getWidth() +
                        leftPartOffset +
                        siblingSpace +
                        rightPartOffset,
                nodeTextSprite.getHeight() + 1);

        int leftArrowLength = Math.max(1,
                leftChildTextSprite.getWidth() +
                        leftPartOffset
                        - aLeft + 1
                        - leftChildDescriptor.rootNodeOffset
                        - leftChildDescriptor.rootNodeWidth / 2);
        int rightArrowLength = Math.max(1,
                rightPartOffset +
                        rightChildDescriptor.rootNodeOffset +
                        rightChildDescriptor.rootNodeWidth / 2 -
                        aRight);

        int totalArrowLength = leftArrowLength + rightArrowLength;
        int nodeSpriteShift = totalArrowLength / 2 - leftArrowLength;

        subtreeTextSprite.apply(nodeTextSprite,
                nodeSpriteShift +
                        leftChildTextSprite.getWidth() +
                        leftPartOffset - aLeft,
                0);

        rightArrowLength = totalArrowLength / 2;
        leftArrowLength = totalArrowLength - rightArrowLength;

        int arrowStartX = leftChildTextSprite.getWidth() + leftPartOffset
                - aLeft
                + nodeSpriteShift;
        int arrowY = nodeTextSprite.getHeight() - 2;

        for (int x = 0; x < leftArrowLength; ++x) {
            subtreeTextSprite.setChar(arrowStartX - x , arrowY, '-');
        }

        subtreeTextSprite.setChar(Math.max(arrowStartX - leftArrowLength,0),
                arrowY,
                '+');

        subtreeTextSprite.setChar(Math.max(arrowStartX - leftArrowLength,0),
                arrowY + 1,
                '|');

        subtreeTextSprite.setChar(Math.max(arrowStartX - leftArrowLength,0),
                arrowY + 2,
                arrowTipCharacter);

        arrowStartX = leftChildTextSprite.getWidth()
                + leftPartOffset
                - aLeft
                + nodeTextSprite.getWidth()
                + nodeSpriteShift;

        for (int x = 0; x < rightArrowLength; ++x) {
            subtreeTextSprite.setChar(arrowStartX + x, arrowY, '-');
        }

        subtreeTextSprite.setChar(arrowStartX + rightArrowLength, arrowY, '+');
        subtreeTextSprite.setChar(arrowStartX + rightArrowLength,
                arrowY + 1,
                '|');

        subtreeTextSprite.setChar(arrowStartX + rightArrowLength,
                arrowY + 2,
                arrowTipCharacter);

        subtreeDescriptor.rootNodeOffset = leftChildTextSprite.getWidth()
                + leftPartOffset
                - aLeft;

        subtreeDescriptor.rootNodeWidth = nodeTextSprite.getWidth();
        subtreeDescriptor.textSprite = subtreeTextSprite;
        return subtreeDescriptor;
    }

    private SubtreeDescriptor printWithLeftChildImpl(
            node node,
            DefaultBinaryTreeNodePrinter<T> nodePrinter) {
        SubtreeDescriptor subtreeDescriptor = new SubtreeDescriptor();
        SubtreeDescriptor leftChildDescriptor = printImpl(node.left,
                nodePrinter);

        TextSprite nodeTextSprite = nodePrinter.print(node);
        TextSprite leftChildTextSprite = leftChildDescriptor.textSprite;

        // The height of the resulting text sprite.
        int subtreeTextSpriteHeight = 1 + nodeTextSprite.getHeight()
                + leftChildTextSprite.getHeight();

        int a = (nodeTextSprite.getWidth() - siblingSpace) / 2;

        int b = leftChildDescriptor.textSprite.getWidth()
                - leftChildDescriptor.rootNodeOffset
                - leftChildDescriptor.rootNodeWidth;

        int leftPartOffset = 0;

        if (a + 2 > b  + leftChildDescriptor.rootNodeWidth) {
            leftPartOffset = a + 2 - b - leftChildDescriptor.rootNodeWidth;
        }

        // The width of the resulting text sprite.
        int subtreeTextSpriteWidth =
                leftChildTextSprite.getWidth() +
                        leftPartOffset +
                        nodeTextSprite.getWidth() -
                        a;

        TextSprite subtreeTextSprite = new TextSprite(subtreeTextSpriteWidth,
                subtreeTextSpriteHeight);
        subtreeTextSprite.apply(nodeTextSprite,
                leftChildDescriptor.textSprite.getWidth() +
                        leftPartOffset - a,
                0);

        subtreeTextSprite.apply(leftChildTextSprite,
                0,
                nodeTextSprite.getHeight() + 1);

        int arrowLength = Math.max(1, leftChildTextSprite.getWidth() +
                leftPartOffset
                - a + 1
                - leftChildDescriptor.rootNodeOffset
                - leftChildDescriptor.rootNodeWidth / 2);

        int arrowStartX = leftChildDescriptor.textSprite.getWidth()
                + leftPartOffset - a;

        int arrowY = nodeTextSprite.getHeight() - 2;

        for (int x = 0; x < arrowLength; ++x) {
            subtreeTextSprite.setChar(arrowStartX - x - 1, arrowY, '-');
        }

        subtreeTextSprite.setChar(arrowStartX - arrowLength, arrowY, '+');
        subtreeTextSprite.setChar(arrowStartX - arrowLength, arrowY + 1, '|');
        subtreeTextSprite.setChar(arrowStartX - arrowLength, arrowY + 2, '|');

        subtreeDescriptor.rootNodeOffset = leftChildTextSprite.getWidth()
                + leftPartOffset - a;
        subtreeDescriptor.rootNodeWidth = nodeTextSprite.getWidth();
        subtreeDescriptor.textSprite = subtreeTextSprite;
        return subtreeDescriptor;
    }

    private SubtreeDescriptor printWithRightChildImpl(
            node node, DefaultBinaryTreeNodePrinter<T> nodePrinter) {
        SubtreeDescriptor subtreeDescriptor = new SubtreeDescriptor();
        SubtreeDescriptor rightChildDescriptor = printImpl(node.left, nodePrinter);

        TextSprite nodeTextSprite = nodePrinter.print(node);
        TextSprite rightChildTextSprite = rightChildDescriptor.textSprite;

        // The height of the resulting text sprite.
        int subtreeTextSpriteHeight = 1 + nodeTextSprite.getHeight()
                + rightChildTextSprite.getHeight();

        // Number of spaces on the right side of the sibling separator.
        int a = (nodeTextSprite.getWidth() - siblingSpace) / 2;

        int rightPartOffset = 0;

        if (rightChildDescriptor.rootNodeOffset +
                rightChildDescriptor.rootNodeWidth < a + 2) {
            rightPartOffset = a + 2 - rightChildDescriptor.rootNodeOffset -
                    rightChildDescriptor.rootNodeWidth;
        }

        // The width of the resulting text sprite.
        int subtreeTextSpriteWidth =
                nodeTextSprite.getWidth()
                        - a
                        + rightPartOffset
                        + rightChildTextSprite.getWidth();

        TextSprite subtreeTextSprite = new TextSprite(subtreeTextSpriteWidth,
                subtreeTextSpriteHeight);
        subtreeTextSprite.apply(nodeTextSprite, 0, 0);
        subtreeTextSprite.apply(rightChildTextSprite,
                nodeTextSprite.getWidth() - a + rightPartOffset,
                1 + nodeTextSprite.getHeight());

        int arrowLength = Math.max(1,
                rightPartOffset +
                        rightChildDescriptor.rootNodeOffset +
                        rightChildDescriptor.rootNodeWidth / 2 - a);

        int arrowStartX = nodeTextSprite.getWidth();
        int arrowY = nodeTextSprite.getHeight() - 2;

        for (int x = 0; x < arrowLength; ++x) {
            subtreeTextSprite.setChar(arrowStartX + x, arrowY, '-');
        }

        subtreeTextSprite.setChar(arrowStartX + arrowLength, arrowY, '+');
        subtreeTextSprite.setChar(arrowStartX + arrowLength, arrowY + 1, '|');
        subtreeTextSprite.setChar(arrowStartX + arrowLength, arrowY + 2, '|');

        subtreeDescriptor.rootNodeOffset = 0;
        subtreeDescriptor.rootNodeWidth = nodeTextSprite.getWidth();
        subtreeDescriptor.textSprite = subtreeTextSprite;
        return subtreeDescriptor;
    }

    private int checkSiblingSpace(int siblingSpace) {
        if (siblingSpace < 0) {
            throw new IllegalArgumentException("Sibling space is negative: " +
                    siblingSpace);
        }

        return siblingSpace;
    }
}
class Utils {

    public static void setEmptyTextSpriteCellsToSpace(TextSprite textSprite) {
        for (int y = 0; y < textSprite.getHeight(); ++y) {
            for (int x = 0; x < textSprite.getWidth(); ++x) {
                char c = textSprite.getChar(x, y);

                if (c == '\u0000') {
                    textSprite.setChar(x, y, ' ');
                }
            }
        }
    }
}
public class MaxHeap {


    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        boolean flag=true;
        Heap h=new Heap();
         while(flag)
         {
             System.out.print("Please input your operation:");
             int op=cin.nextInt();
             switch (op){
                 case 0:
                     System.out.println("Initialize a new heap");
                     h.init();
                     System.out.println("Initialization complete!");
                     break;
                 case 1:
                     System.out.print("Insert a key value:");
                     h.insert(cin.nextInt());
                     System.out.println("Insert complete!");
                     break;
                 case 2:
                     System.out.print("Increase Key,input a vertex:");
                     int v=cin.nextInt();
                     System.out.print("Input the key value:");
                     h.increaseKey(v,cin.nextInt());
                     System.out.println("Increase Key complete!");
                     break;
                 case 3:
                     h.heapSort(h);
                     System.out.println("Heap sort complete!");
                     break;
                 case 4:
                     System.out.println("---------Heap structure----------");
                     DefaultBinaryTreeNodePrinter<Integer> nodePrinter =
                             new DefaultBinaryTreeNodePrinter<>();
                     DefaultBinaryTreePrinter<Integer> printer =
                             new DefaultBinaryTreePrinter<>();
                     System.out.println(printer.print(h.head, nodePrinter));
                     //h.output(h.head);
                     break;
                 case 5:
                     if(h.sortedArray.size()<1){
                         System.out.println("Heap not sort yet,please do opeation 3 first.");
                     }
                     else{
                         System.out.print("Heapsort result:");
                         h.outputSortResult();
                    }
                     break;
                 case 6:
                     System.out.print("Input an array to build a heap.Your array length:");
                     int len=cin.nextInt();
                     System.out.print("Input the element:");
                     List<Integer> arr=new ArrayList<Integer>();
                     for(int i=0;i<len;i++)
                         arr.add(cin.nextInt());
                     h.arrayBuildHeap(h,arr);
                     System.out.println("Build complete!");
                     break;
                 case 9:
                     System.out.println("exit");
                     flag=false;
                     break;
                 default:
                     break;
             }
         }
    }
}
项目运行测试结果:

res.png

3.Maven项目导出jar包

我们新建一个Maven项目

cr7.jpg

之后找到项目的pom文件,输入一个maven-plugin-shade的启动依赖。

maven-plugin-shade必须和Maven构建生命周期中的package阶段绑定,也就是说,当执行mvn package时会自动触发shade。

我们的项目主类的路径为com.joy187.MaxHeap

cr8.jpg
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>maxHeapProject</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <configuration>
                    <transformers>
                        <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <!--你的项目主类名称-->
                            <mainClass>com.joy187.MaxHeap</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
刷新Maven项目后找到package并点击,进行打包操作

cr2.jpg

打包完成出现success字样:

cr3.jpg

4.cmd控制台运行项目

项目构建好后,我们找到target文件夹,里面不带有original的就是我们的可执行jar包了:

cr6.jpg

在该文件夹中输入cmd进入控制台:

cc.jpg

控制台输入指令:

java -jar 项目名称.jar
cr1.jpg

之后就可以运行项目了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay_fearless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值