查找与排序(一)
查找与排序(二)
查找与排序(四)
二叉树的遍历
import java.util.Scanner;
public class LianXi {
//前序遍历
public static void preOrder(int []arr, int i){
if(i >= arr.length)
return;
System.out.print(arr[i] + " "); //输出根节点
preOrder(arr, 2 * i + 1); //递归输出左子树
preOrder(arr, 2 * i + 2); //递归输出右子树
}
//中序遍历
public static void inOrder(int []arr, int i){
if(i >= arr.length)
return;
inOrder(arr, 2 * i + 1); //递归输出左子树
System.out.print(arr[i] + " "); //输出根节点
inOrder(arr, 2 * i + 2); //递归输出右子树
}
//后序遍历
public static void postOrder(int []arr, int i){
if(i >= arr.length)
return;
postOrder(arr, 2 * i + 1); //递归输出左子树
postOrder(arr, 2 * i + 2); //递归输出右子树
System.out.print(arr[i] + " "); //输出根节点
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int []arr = new int[N];
for(int i = 0 ; i<N; i++){
arr[i] = in.nextInt();
}
System.out.println("初始数组为:");
for(int i = 0 ; i<N; i++){
System.out.print(arr[i] + " ");
}
System.out.println("\n");
System.out.println("前序遍历:");
preOrder(arr, 0);
System.out.println("\n");
System.out.println("中序遍历:");
inOrder(arr, 0);
System.out.println("\n");
System.out.println("后序遍历:");
postOrder(arr, 0);
}
}
堆
堆的概念
- 二叉堆是完全二叉树或者是近似完全二叉树。
- 二叉堆满足二个特性:
1、父节点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2、每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆) - 任意节点的值都是大于其子节点的值——大顶堆
- 任意节点的值都是小于其子节点的值——小顶堆
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
堆排序
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
步骤
1、构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。
2、将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。
最小堆排序
import java.util.Scanner;
public class LianXi {
/*
* MinHeap(A){
* n = A.length;
* for i from n/2-1 down to 0{
* MinHeapFixDown(A,i,n);
* }
* }
* MinHeapFixDown(A,i,n){
* // 找到左右孩子
* left = 2 * i + 1;
* right = 2 * i + 2;
* //左孩子已经越界,i就是叶子节点
* if(left>=n){
* return;
* }
*
* min = left;
* if(right >= n){
* min = left;
* }
* else{
* if(A[right] < A[left])
* min = right;
*
* }
* //min指向了左右孩子中较小的那个
* //如果A[i]比两个孩子都要小,不用调整
* if(A[i] <= A[min]){
* return ;
* }
* // 否则,找到两个孩子中较小的,和i交换
* swap(A,i,min)
* //小孩子那个位置的值发生了变化,i变更为小孩子那个位置,递归调整
* MinHeapFixDown(A,min,n);
*
* sort(A):
* //先对A进行堆化
* MinHeap(A);
* for(int x = n-1; x>=0; x--)
* //把堆顶,0号元素和最后一个元素对调
* swap(A,0,x);
* //缩小堆的范围,对堆顶元素进行向下调整
* MinHeapFixDown(A,0,x-1)
*/
public static void MinHeap(int []A){
int n = A.length;
for(int i = n/2-1; i>=0; i--){
MinHeapFixDown(A, i, n);
}
}
public static void MinHeapFixDown(int []A, int i, int n){
int left = 2 * i + 1;
int right = 2 * i + 2;
if(left >= n){
return ;
}
int min = left;
if(right >= n){
min = left;
}
else{
if(A[right] < A[left]){
min = right;
}
}
if(A[i] <= A[min]){
return ;
}
swap(A,i,min);
MinHeapFixDown(A, min, n);
}
public static void sort(int []A){
MinHeap(A);
for(int x = A.length-1; x>=0; x--){
swap(A,0,x);
MinHeapFixDown(A, 0, x-1);
}
}
public static void swap(int[]A, int i, int min){
int temp = A[i];
A[i] = A[min];
A[min] = temp;
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int []A = new int[N];
for(int i = 0; i<N; i++){
A[i] = in.nextInt();
}
System.out.println("初始数组为:");
for(int i = 0; i<N; i++){
System.out.print(A[i]+ " ");
}
System.out.println("\n");
sort(A);
System.out.println("最小堆排序后数组为:");
for(int i = 0; i<N; i++){
System.out.print(A[i] + " ");
}
}
}