软件工程第四次作业
这个作业属于软件工程 | https://edu.cnblogs.com/campus/zswxy/2018SE |
---|---|
这个作业要求实现排序算法和和二叉树的先,中,后以及层次遍历 | https://edu.cnblogs.com/campus/zswxy/2018SE/homework/11406 |
这个作业的目标是学习数据结构 | 学会一些排序算法和理解二叉数 |
其他参考文献 | ... |
一.给定一个序列,每次询问第l个数到第r个数中第k大的数.
解题思路
1.实现思路
(本题的核心就是排序,考虑到时间复杂度,我选择了比较快的快速排序算法。)
先从给定的序列中截取所需的询问序列,而询问序列的长度就是r-l+1,再排序,排序后 这个序列中第k大的数就是r-l+1-k(序列的长度-k)
2.具体实现
(1)考虑到空间复杂度,不使用过多中间变量,设置数组arr存储序列,arrCopy作为询问序列的中间数组,一个二维数组marks存储m个询问序列的条件l,r,k 。
(2)先用java中Scanner类获得键盘输入数据,并将序列值存入数组arr,询问序列条件存入二维数组marks;
(3)再在for循环中根据marks中的条件依次从arr中截取出询问序列并排序,再输出第k大的值;
解题代码
`
public class test {
private static int[] arr;
private static int[][] marks;
private static int[] arrCopy;
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
System.out.println("请按本题规范格式输入数据");
//1.获取序列长度,并创建一个数组存储该序列
arr=new int[sc.nextInt()];
sc.nextLine();//消除空格
//2.将序列填进数组
for(int i=0;i<arr.length;i++){
arr[i]=sc.nextInt();
}
sc.nextLine();//消除空格
//3.获取询问个数,并创建m行3列的二维数组
marks=new int[sc.nextInt()][3];
//4.获取多个询问序列
for(int i=0;i<marks.length;i++){
if(i==(marks.length-1)){
}else{
sc.nextLine();//消除空格
}
for(int j=0;j<3;j++){
marks[i][j]=sc.nextInt();
}
if(marks[i][2]>(marks[i][1]-marks[i][0]+1)){
System.out.println("输入格式错误");
return;
}
}
//5.根据约束条件copy从序列中copy一个数组
for(int i=0;i<marks.length;i++){
arrCopy=new int[marks[i][1]-marks[i][0]+1];
System.arraycopy(arr,marks[i][0]-1, arrCopy,0, marks[i][1]-marks[i][0]+1);
//6.排序,并查找k大的数输出
quickSort(arrCopy,0,arrCopy.length-1);
System.out.println(arrCopy[marks[i][1]-marks[i][0]+1-marks[i][2]]);
}
}
//快速排序
public static void quickSort(int[] arr, int left, int right) {
if(left > right) {
return;
}
// base中存放基准数
int base = arr[left];
int i = left, j = right;
while(i != j) {
// 从右边开始往左找,直到找到比base值小的数
while(arr[j] >= base && i < j) {
j--;
}
// 再从左往右边找,直到找到比base值大的数
while(arr[i] <= base && i < j) {
i++;
}
// 上面的循环结束表示找到了位置或者(i>=j)了,交换两个数在数组中的位置
if(i < j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
// 基准数归位
arr[left] = arr[i];
arr[i] = base;
// 递归排序
quickSort(arr, left, i - 1);
quickSort(arr, i + 1, right);
}
}
`
对数器
根据对数器的条件,我用Java自带的Arrays.sort()方法和自己实现的快速排序算法对比
`public class check {
public static void main(String[] args){
int testtime =1000;
int MaxSize =10;
int MaxValue =1000;
boolean isSucceed=true;
int[] arr1;
int[] arr2;
int[] arr3;
for(int i=1;i<=testtime;i++){
arr1=getRedomArray(MaxSize,MaxValue);
arr2=copyArray(arr1);
arr3=copyArray(arr2);//如果失败则打印该样本
systemSort(arr1);
quickSort(arr2,0,arr2.length-1);
if(!isEqual(arr1,arr2)){
isSucceed=false;
System.out.println(Arrays.toString(arr3));
break;
}
}
System.out.println(isSucceed?"该算法正确":"该算法不正确");
int [] arr=getRedomArray(MaxSize,MaxValue);
System.out.println(Arrays.toString(arr));
quickSort(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
//数组复制
public static int[] copyArray(int[] arr1){
int[] arr2=new int[arr1.length];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
return arr2;
}
//随机随机样本产生器
public static int[] getRedomArray(int MaxSize,int MaxValue){
int[] temp=new int[(int) ((MaxSize+1)*Math.random())];
for(int i=0;i<temp.length;i++){
temp[i]=(int)((MaxValue+1)*Math.random()-(int)(MaxValue*Math.random()));
}
return temp;
}
//对比方法
public static boolean isEqual(int[] arr1,int[] arr2){
if((arr1==null&&arr2!=null)||(arr1!=null&&arr2==null)){
return false;
}
if(arr1==null&&arr2==null){
return true;
}
if(arr1.length!=arr2.length){
return false;
}
for(int i=0;i<arr1.length;i++){
if(arr1[i]!=arr2[i]){
return false;
}
}
return true;
}
//系统排序
public static void systemSort(int[] arr){
Arrays.sort(arr);
}
//快速排序
public static void quickSort(int[] arr, int low, int high) {
if (low>=high){
return;
}
//找出基准值temp
int index = getIndex(arr, low, high);
//左排序
quickSort(arr,0,index-1);
//右排序
quickSort(arr,index+1,high);
}
public static int getIndex(int[] arr, int low, int high) {
int temp=arr[low];
while (low<high){
//右排序
while (low<high&&arr[high]>=temp){
//如果arr[high]>=temp,high--
high--;
}
//把arr[high]的值赋给arr[low]
arr[low]=arr[high];
//左排序
while (low<high&&arr[low]<temp){
//如果arr[low]<temp,low++
low++;
}
//把arr[low]的值赋给arr[high]
arr[high]=arr[low];
}
//复位
arr[low]=temp;
return low;
}
}`
二.实现二叉树的先,中,后及层次遍历.
解题思路
1.顾名思义,先序遍历就是先遍历根子树,后遍历左子树,再遍历右子树。
中序遍历就是先遍历左子树,后遍历根子树,再遍历右子树。
后序遍历就是先遍历左子树,后遍历右子树,再遍历根子树。
先中后序遍历用递归实现即可
2.层次遍历就依层遍历。
层次遍历需借助Java中队列LinkedList和while循环来实现,先将根节点放入队列中,再取出根节点打印节点值,再依次放入该节点的左右节点,
每当前一层节点遍历完就从队列中取出,放入下层节点,循环遍历;
解题代码
`public class Main {
public static void main(String[] args) {
/*
作业要求:叉树的先、中、后 序遍历与层级遍历
自己实现四个方法,main方法中调用,将结果打印到控制台
*/
/* 二叉树的结构
A
/ \
T 6
/
D
/ \
N 5
/ \ /
B 4 1
\
9
*/
Node root = into();
// 先序遍历
A(root);
System.out.println();
// 中序遍历
B(root);
System.out.println();
// 后续遍历
C(root);
System.out.println();
// 层级遍历
D(root);
}
private static void visit(Node node){
System.out.print(node.data);
}
private static void A(Node node) {
if(node!=null){
visit(node);
A(node.l);
A(node.r);
}
// TODO 先序遍历
}
private static void B(Node node) {
// TODO 中序遍历
if(node!=null){
B(node.l);
visit(node);
B(node.r);
}
}
private static void C(Node node) {
// TODO 后续遍历
if(node!=null){
C(node.l);
C(node.r);
visit(node);
}
}
private static void D(Node node) {
// TODO 层级遍历
if(node==null){
return;
}
LinkedList<Node> queue=new LinkedList();
Node temp;
queue.offer(node);
while(!queue.isEmpty()){
temp=queue.poll();
visit(temp);
if(temp.l!=null){
queue.offer(temp.l);
}
if(temp.r!=null){
queue.offer(temp.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 Object getDate(Node node){
return node.data;
}
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;
}
}
}
`