2020软件工程作业04

2020软件工程作业04

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/2018SE
这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/2018SE/homework/11406
这个作业的目标 1.用排序算法找数组中第K大的数(时间复杂度所耗时间越小越好)2.用搜索算法实现二叉树的先、中、后序遍历与层级遍历,将结果打印到控制台
其他参考文献 二叉树的遍历方法之层序-先序-中序-后序遍历的简单讲解和代码示例:https://blog.csdn.net/why850901938/article/details/51055024

第一题:寻找数组中第K大的数

解题思路:

首先第一行要键盘输入一个n用来表示序列的长度,第二行输入的实现我是先定义了一个整型数组,长度n+1由键盘输入,a[0]=0,这样才能让每个下标与我在键盘输入的数字的顺序对应上,从a[1]开始对应第一个数,即序列元素从1开始。第三行输入询问的个数,用键盘输入即可。接下来的m行,每行输入l,r,k,并且再定义一个数组用来存放要排序的数的数组,之后写for循环,把数组a的值赋给数组temp,最后调用内置排序方法,因为sort函数是从小到大排序的,而题目中要从大到小第k大,那么排序出来的倒数第一个是最大数,以此类推temp[r-l+2-k]即是从大往小第k大的数。

解题代码:

package pxsf;

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	 public static void main(String[] args){
	        Scanner sc=new Scanner(System.in);
	        int n=sc.nextInt();
	        int []a=new int [n+1];
	        a[0]=0;//使其他下标一致	        
	        for (int i = 1; i <=n ; i++) {
	            a[i]=sc.nextInt();//输入给定的序列
	        }
	        int m=sc.nextInt();//输入要询问的个数
	        for (int i=1;i<=m;i++){
	            int l=sc.nextInt();// 输入从左往右第l个数
	            int r=sc.nextInt();// 输入从左往右第r个数
	            int k=sc.nextInt();// 输入指定k
	            int [] temp=new int [r-l+2];//用于存放要排序的数的数组
	            temp[0]=0;
	            int b=l;
	            for (int j=1;j<=r-l+1;j++){//把要排序的数转移到该数组
	            	temp[j]=a[b];
	                b++;
	            }
	            Arrays.sort(temp);//调用sort函数排序
	         System.out.println(temp[r-l+2-k]);//输出第k大的数
	        }
	 }
}

控制台输出效果

第二题:二叉树的先、中、后 序遍历与层级遍历

解题思路:

  • 先序遍历:其访问顺序为先到根节点,再到左节点,最后到右节点。用堆栈的方法实现先序的遍历,要用到栈来暂存节点,新建一个游标节点为根节点,然后要通过while语句判断栈和节点是否都为空,只要有一个非空就进入循环,循环内节点非空则输出该节点的值,总之访问完根节点就一直往左找,等左子树空了就开始考虑右子树,如果栈空了就不在考虑。
  • 中序遍历:其访问顺序为左子树、再到根节点、最后到右子树。用堆栈的方法实现中序的遍历,如果节点不是空的,暂存此节点,游标等于左子树,然后如果栈不是空的,就输出存的节点也就是根节点,然后让游标等于右子树。
  • 后序遍历:其访问顺序是先访问左节点,再访问右节点,最后才访问根节点。用堆栈的方法实现后序的遍历。前面思路一样,while判断节点是不是空的,非空则暂存节点,游标节点等于左子树,然后看节点的右子树,如果为空或被访问了就可以输出当前节点的值,然后让访问和节点为空,否则就继续访问右子树。
  • 层序遍历:按照二叉树的层次由上到下的进行遍历,每一层要求访问的顺序为从左到右。利用队列的方法实现层次遍历。根节点先入队列,如果根节点不为空,则取出列队头节点,输出队列的头节点的值,头节点的左子树不为空,则左子树入队列,右子树不为空也入队列,再看根节点是否为空,依次进行下去。

解题代码:

package Tree;

import java.util.LinkedList;
import java.util.Stack;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
        作业要求:叉树的先、中、后 序遍历与层级遍历
        自己实现四个方法,main方法中调用,将结果打印到控制台
     */
    /*  二叉树的结构
                 A
                / \
               T   6
              /
             D
           /   \
          N     5
         / \    /
        B   4  1
             \
              9
     */
    Node root = into();
    // 先序遍历
    A(root);
    // 中序遍历
    B(root);
    // 后序遍历
    C(root);
    // 层级遍历
    D(root);

}

private static void A(Node root) {
    // TODO 先序遍历
    Stack<Node> NodeStack = new Stack<Node>();// 用来暂存节点的栈
    Node node = root;// 新建一个游标节点为根节点
        while (node != null || !NodeStack.isEmpty()) {// 不同时满足这两点,进入循环
        while (node != null) {
            System.out.print(node.data + " ");// 如果当前访问节点非空,则输出该节点的值
            NodeStack.push(node); // 暂存该节点
            node = node.l;
        }
        if (!NodeStack.isEmpty()) {// 如果左子树为空,则考虑右子树
            node = NodeStack.pop();
            node = node.r;// 弹出栈顶元素,将游标等于该节点的右子树
        }
    }
}
private static void B(Node root) {
    // TODO 中序遍历
	Stack<Node> NodeStack = new Stack<Node>();
    Node node = root;
    while (node != null || !NodeStack.isEmpty()) {
        while (node != null) {
            NodeStack.push(node);
            node = node.l;
        }
        if (!NodeStack.isEmpty()) {
            node = NodeStack.pop();
            System.out.print(node.data + " ");
            node = node.r;
        }
    }
}
private static void C(Node root) {
    // TODO 后序遍历
	Stack<Node> NodeStack = new Stack<Node>();
    Node node = root;
    Node lastVisit = root;
    while (node != null || !NodeStack.isEmpty()) {
        while (node != null) {
            NodeStack.push(node);
            node = node.l;
        }
        //查看当前栈顶元素
        node = NodeStack.peek();
        //如果其右子树也为空,或者右子树已经访问
        //则可以直接输出当前节点的值
        if (node.r == null || node.r == lastVisit) {
            System.out.print(node.data + " ");
            NodeStack.pop();
            lastVisit = node;
            node = null;
        } else {
            //否则,继续遍历右子树
            node = node.r;
        }
    }
}

private static void D(Node root) {
    // TODO 层级遍历
	LinkedList<Node> queue=new LinkedList<>();
    Node p;
    queue.push(root);
    while(!queue.isEmpty())
    {
        p=queue.removeFirst();
        System.out.print(p.data+ " ");
        if (p.l!=null)
            queue.addLast(p.l);
        if (p.r!=null)
            queue.addLast(p.r);
    }
}


// 构建一颗树,返回根节点
private static Node into(){
    Node root = new Node("A");
    Node node1 = new Node("T");
    Node node2 = new Node("D");
    Node node3 = new Node("N");
    Node node4 = new Node("B");
    Node node5 = new Node("6");
    Node node6 = new Node("5");
    Node node7 = new Node("4");
    Node node8 = new Node("9");
    Node node9 = new Node("1");
    root.l = node1;
    node1.l = node2;
    node2.l = node3;
    node2.r = node6;
    node3.r = node7;
    node7.r = node8;
    node6.l = node9;
    node3.l = node4;
    root.r = node5;
    return root;
}

// 节点
static class Node{
    // 数据
    Object data;
    // 左孩子
    Node l;
    // 右孩子
    Node r;
    

    public Node(){}

    public Node(Object data) {
        this.data = data;
        this.l = null;
        this.r = null;
    }

    public Node(Object data, Node l, Node r) {
        this.data = data;
        this.l = l;
        this.r = r;
    }
}
}

控制台输出效果


先序遍历:

中序遍历:

后序遍历:

层级遍历:

posted @ 2020-10-24 19:22  FFF21  阅读(301)  评论(0编辑  收藏  举报