数据结构实验课:打印树形二叉搜索树;用睡眠排序

下面是作业要求:


ICSI 213 Data Structures Lab

Week 12 Lab 7, November 27th.

Topics:

 Binary Search Tree

Study materials:

 See lecture notes and relevant materials from the textbook.Instructions:

Write a program that can convert a sorted array into a binary search tree. The program allows the user to enter a number n, generates an array of n random integers, sorts the array, and then converts the sorted array into a binary search tree. You can display the tree by printing each node, its left child, and its right child per line.

ICSI 213数据结构实验课
第12周实验7,11月27日。
话题:
二进制搜索树
学习资料:
参阅教科书中的讲义和相关材料。说明:
编写一个可以将排序数组转换为二叉搜索树的程序。 该程序允许用户输入数字n,生成n个随机整数数组,对数组进行排序,然后将排序后的数组转换为二叉搜索树。 您可以通过每行打印每个节点,其左子节点和右子节点来显示树。


实验课作业,反正必须写,不如写点好玩儿的东西,用上了前段时间刷屏的“老板有毛病吧,写完排序就让我走”这个段子里的睡眠排序大法。

其实睡眠排序问题很多,比如不能排负数;当数字相差很小,会不精准;当出现一个很大的数字,会睡眠很长时间。总而言之,在实际生活中,这玩意儿没什么卵用,但是不妨在无关紧要的地方写着玩儿。

其实在把睡眠排序用到作业里的过程中遇到了不少问题,最大的问题就是排序的结果不容易取出来,一是睡眠排序的原理决定了你没办法用数组来存结果,因为你也不知道谁先出来,二是多线程用静态全局变量也不能被各个线程读到,第一个问题还算好办,每当一个线程睡眠完毕,就往一个stack里push这个元素就好了,但是第二个问题就没那么方便,只能想办法让多个线程之间共享数据,最后的解决方案是将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个SortThread对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样实现针对该数据进行的各个操作的互斥和通信。

这还没完,各个SortThread还没跑完,主线程就已经开始试图从stack里取数据了,当然什么都没有,于是被糊了一脸bug,还出现了一边抱错一边输出正确结果的奇观,(一些SortThread跑完就有结果了),每个SortThread跑的时间不一样于是只能按照SortThread可能的最长时间来让主线程等着,取到stack后还不能直接发回去(这个stack在ShareData里),要把他往SleepSort里的另外一个stack里来倒腾一遍然后才能return回去。

大致的坑就这么多,代码在下面。


  • Driver.java

import Controller.Controller;

/**
 * filename: Driver.java
 * @author:Xu Wanxiang
 * date:2018.11.27
 * description: this class start the project.
 * @version 1.0
 */
public class Driver {

    public static void main(String[] args) {

        new Controller();
    }
}

  • Controller.java

package Controller;
import java.util.*;
import BinarySearchTree.*;
import Sort.*;

/**
 * filename: Controller.java
 * package:Controller
 * @author:Xu Wanxiang
 * date:2018.11.27
 * description: this class let the user to choose the function that they want to use.
 * @version 1.0
 */

public class Controller {

    public static Stack stack = new Stack();

    public  Controller(){

        System.out.println("Please type the size of the tree you wish to generate");
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Integer> al = new ArrayList<>();

        for(int i = 0;i < n;i ++){
            Random randon = new Random();
            int r = randon.nextInt(100);
            al.add(r);
        }

        System.out.print(al);
        System.out.println("\n");
        int[]AL = new int[al.size()];
        for (int i = 0;i < al.size();i ++){
            AL[i] = al.get(i);
        }

        SleepSort SS = new SleepSort(AL);
        stack = SS.getStack();

        BinarySearchTree<Integer, String> bst = new BinarySearchTree<Integer, String>();

//        while((!stack.empty())){
//            System.out.println((int)stack.pop());
//        }


        while (!(stack.empty())){
            bst.insert((int)stack.pop(),"a");
        }

        //print begin by root of the BinarySearchTree
        TreePrintUtil.pirnt(bst.getRoot());
    }
}

  • SleepSort.java

package Sort;
import java.util.*;
import Controller.*;


/**
 * filename: SleepSort.java
 * package:Sort
 * @author:Xu Wanxiang
 * date:2018.11.27
 * description: this class sort a array.
 * @version 1.0
 */
public class SleepSort {

    public Stack<Integer> stack2 = new Stack<Integer>();
    // Create a stack object
    public SleepSort(int[] arr){


        final ShareData shareData = new ShareData();


        //Create a sleep thread
        SortThread[] sortThreads = new SortThread[arr.length];

        //Initialize sleep thread
        for (int i = 0; i < sortThreads.length; i++) {
            sortThreads[i] = new SortThread(arr[i],shareData);
        }

        for (int i = 0; i < sortThreads.length; i++) {
            sortThreads[i].start();
        }

        try { Thread.sleep ( 10000 ) ;
        } catch (InterruptedException ie){}

        while (!shareData.getStack().empty()){
            stack2.push(shareData.getStack().pop());
        }



    }

    public Stack getStack(){
        return stack2;
    }

    class SortThread extends Thread{
        public int ms;
        private ShareData shareData;

        public  SortThread(int s,ShareData shareData){
            this.shareData = shareData;
            this.ms = s;
        }

        public void run(){
            try {
                sleep(ms*10+10);  //Sleep specified time
            } catch (InterruptedException e) {

                e.printStackTrace();
            }

//        System.out.println(ms);
            shareData.sent(ms);

        }
    }

    static class ShareData{
        Stack<Integer> stack = new Stack<Integer>();

        public synchronized void sent(int ms){
            stack.push(ms);
        }

        public Stack<Integer> getStack() {
            return stack;
        }
    }
}

  • TreeNode.java

package BinarySearchTree;

/**
 * filename: TreeNode.java
 * package:BinarySearchTree
 * @author:Xu Wanxiang
 * date:2018.11.27
 * description: this class is TreeNode.
 * @version 1.0
 */
public interface TreeNode {

    String getPrintInfo();

    TreeNode getLeftChild();

    TreeNode getRightChild();
}

  • BinarySearchTree.java

package BinarySearchTree;

/**
 * filename: BinarySearchTree.java
 * package:BinarySearchTree
 * @author:Xu Wanxiang
 * date:2018.11.27
 * description: this class construct BinarySearchTree.
 * @version 1.0
 */

public class BinarySearchTree<K extends Comparable<K>, V> {
    private int count;
    private Node<K, V> root;
    private int maxLevel;

    public int size() {
        return count;
    }

    public boolean isEmpty() {
        return count == 0;
    }

    public void insert(K k, V v) {
        Node<K, V> node = new Node<>(k, v);
        if (insertToNode(root, node, 0)) {
            // If it is inserted, count+1
            count++;
        }
    }

    public Node getRoot() {
        return root;
    }

    /**
     *
     * @param parint
     * @param node
     * @return If the new returns true, if only the update returns false
     */
    private boolean insertToNode(Node<K, V> parent, Node<K, V> node, int level) {
        if (root == null) {
            root = node;
            maxLevel = 1;
            return true;
        }
        if (parent.k.compareTo(node.k) == 0) {
            // update if key is the same
            parent.v = node.v;
            return false;
        } else if (parent.k.compareTo(node.k) < 0) {
            // If node is larger than parent, insert it into the right subtree
            if (parent.right == null) {
                parent.right = node;
                if (level + 1 > maxLevel) {
                    maxLevel = level + 1;
                }
                return true;
            }
            return insertToNode(parent.right, node, level + 1);
        } else {
            // If the node is smaller than the parent, insert the left subtree
            if (parent.left == null) {
                parent.left = node;
                if (level + 1 > maxLevel) {
                    maxLevel = level + 1;
                }
                return true;
            }
            return insertToNode(parent.left, node, level + 1);
        }

    }

    private static class Node<K extends Comparable<K>, V> implements TreeNode {
        K k;
        V v;
        Node left, right;

        public Node(K k, V v) {
            this.k = k;
            this.v = v;
        }

        @Override
        public String toString() {
            return "[" + k + "]";
        }

        @Override
        public String getPrintInfo() {

            return toString();
        }

        @Override
        public TreeNode getLeftChild() {
            // TODO Auto-generated method stub
            return left;
        }

        @Override
        public TreeNode getRightChild() {
            // TODO Auto-generated method stub
            return right;
        }

    }
}

  • TreePrintUtil.java

package BinarySearchTree;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * filename: TreePrintUtil.java
 * package:BinarySearchTree
 * @author:Xu Wanxiang
 * date:2018.11.27
 * description: this class print the BinarySearchTree just like a tree.
 * @version 1.0
 */

public class TreePrintUtil {
    public static void pirnt(TreeNode root) {
        // Find the maximum offset on the left
        int maxLeftOffset = findMaxOffset(root, 0, true);
        int maxRightOffset = findMaxOffset(root, 0, false);
        int offset = Math.max(maxLeftOffset, maxRightOffset);
        // Calculate the maximum offset
        Map<Integer, PrintLine> lineMap = new HashMap();
        calculateLines(root, offset, lineMap, 0, true);
        Iterator<Integer> lineNumbers = lineMap.keySet().iterator();
        int maxLine = 0;
        while (lineNumbers.hasNext()) {
            int lineNumber = lineNumbers.next();
            if (lineNumber > maxLine) {
                maxLine = lineNumber;
            }
        }
        for (int i = 0; i <= maxLine; i++) {
            PrintLine line = lineMap.get(i);
            if (line != null) {
                System.out.println(line.getLineString());
            }
        }

    }

    private static void calculateLines(TreeNode parent, int offset, Map<Integer, PrintLine> lineMap, int level,
                                       boolean right) {
        if (parent == null) {
            return;
        }
        int nameoffset = parent.toString().length() / 2;
        PrintLine line = lineMap.get(level);
        if (line == null) {
            line = new PrintLine();
            lineMap.put(level, line);
        }
        line.putString(right ? offset : (offset - nameoffset), parent.toString());
        // Determine if there is a next level
        if (parent.getLeftChild() == null && parent.getRightChild() == null) {
            return;
        }
        // If there is, add a split line/\
        PrintLine separateLine = lineMap.get(level + 1);
        if (separateLine == null) {
            separateLine = new PrintLine();
            lineMap.put(level + 1, separateLine);
        }
        if (parent.getLeftChild() != null) {
            separateLine.putString(offset - 1, "/");
            calculateLines(parent.getLeftChild(), offset - nameoffset - 1, lineMap, level + 2, false);
        }
        if (parent.getRightChild() != null) {
            separateLine.putString(offset + nameoffset + 1, "\\");
            calculateLines(parent.getRightChild(), offset + nameoffset + 1, lineMap, level + 2, true);
        }

    }

    private static class PrintLine {
        /**
         * record map of offset and String
         */
        Map<Integer, String> printItemsMap = new HashMap<>();
        int maxOffset = 0;

        public void putString(int offset, String info) {
            printItemsMap.put(offset, info);
            if (offset > maxOffset) {
                maxOffset = offset;
            }
        }

        public String getLineString() {
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; i <= maxOffset; i++) {
                String info = printItemsMap.get(i);
                if (info == null) {
                    buffer.append(" ");
                } else {
                    buffer.append(info);
                    i += info.length();
                }
            }
            return buffer.toString();
        }

    }

    private static int findMaxOffset(TreeNode parent, int offset, boolean findLeft) {
        if (parent != null) {
            offset += parent.toString().length();
        }
        if (findLeft && parent.getLeftChild() != null) {
            offset += 1;
            return findMaxOffset(parent.getLeftChild(), offset, findLeft);
        }
        if (!findLeft && parent.getRightChild() != null) {
            return findMaxOffset(parent.getRightChild(), offset, findLeft);
        }
        return offset;
    }
}

  • test.java

package Test;

import Controller.Controller;
import Sort.SleepSort;
import BinarySearchTree.*;
/**
 * filename: test.java
 * package:Test
 * @author:Xu Wanxiang
 * date:2018.11.27
 * description: this class test the project.
 * @version 1.0
 */
public class test {

    public static void main(String[] args) {

        BinarySearchTree<Integer, String> bst = new BinarySearchTree<Integer, String>();
        bst.insert(10, "a");
        bst.insert(15, "b");
        bst.insert(5, "d");
        bst.insert(9, "e");
        bst.insert(33, "f");
        bst.insert(38, "g");
        bst.insert(1, "h");
        bst.insert(0, "i");
        bst.insert(90, "j");
        bst.insert(100, "k");
        bst.insert(7, "l");
        bst.insert(1, "m");
        //从根开始打印
        TreePrintUtil.pirnt(bst.getRoot());
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值