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;
}
}
}
控制台输出效果
先序遍历:
中序遍历:
后序遍历:
层级遍历: