树的基本概念
1.根节点:处于树结构顶端的节点,没有双亲节点。
2.双亲节点:与该节点链接的上一层节点。
3.路径:从一个节点到另一个结点经过的结点路径。
4.度:一个结点的子节点数量。
5.节点的权:节点中存储的数据。
6.叶子节点:没有子节点的节点。
7.子树:子树。
8.层:树的每一层。
9.树的高度:最大层数。
10.森林:多个树组成的集合称为森林。
二叉树
概念:
任何一个节点的字节点不超过2,二叉树的子节点分为左节点和右节点。
满二叉树:
所有叶子节点都在最后一层,节点的总数为2^n-1,n是树的高度。
完全二叉树:
所有叶子节点都在最后一层或倒数第二层,且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续。
二叉树的存储结构
链式存储的二叉树:
遍历方式:
1.前序遍历:
根节点 -->左子树 -->右子树(先遍历根节点,然后左右)。
前序遍历结果为:ABDEGHCF
2.中序遍历:
左子树 -->根节点 -->右子树(在中间遍历根节点)。
中序遍历结果为:DBGEHACF
3.后序遍历:
左子树 -->右子树 -->根节点(最后遍历根节点)。
后序遍历结果为:DGHEBFCA
查找方式:
在遍历的基础上进行查找,也分为前序,中序和后序。
public TreeNode frontSearch(int i) {
TreeNode target = null;
// 对比当前节点的值
if(this.value == i) {
return this;
// 当前节点不是要查找的节点
}else {
// 查找左儿子
if(leftNode != null) {
// 有可能查到,查不到的话target仍为null
target = leftNode.frontSearch(i);
}
// 如果不为空,说明在左儿子中已经找到
if(target != null) {
return target;
}
// 查找右儿子
if(rightNode != null) {
target = rightNode.frontSearch(i);
}
}
return target;
}
删除节点
// 删除子树
public void delete(int i) {
TreeNode parent = this;
// 判断左儿子
if(parent.leftNode!=null&&parent.leftNode.value==i) {
parent.leftNode=null;
return;
}
// 判断右儿子
if(parent.leftNode!=null&&parent.rightNode.value==i) {
parent.rightNode=null;
return;
}
// 递归检查并删除左儿子
parent=leftNode;
if(parent!=null) {
parent.delete(i);
}
// 递归检查并删除右儿子
parent=rightNode;
if(parent!=null) {
parent.delete(i);
}
}
顺序存储的二叉树
顺序存储的二叉树一般只考虑完全二叉树。
第n个元素的左子节点:2n+1;
第n个元素的右子节点:2n+2;
第n个元素的父节点:(n-1)/2
排序代码:
public void frontShow(int index) {
if(data==null&data.length==0) {
return;
}
// 遍历当前节点的内容
System.out.println(data[index]);
// 2*index + 1
if(2*index+1<data.length) {
frontShow(2*index+1);
}
// 2*index + 2
if(2*index+2<data.length) {
frontShow(2*index+2);
}
}
堆排序
堆:一个近似完全二叉树的结构,并同时满足堆积的性质:即即子节点的键值或索引总是小于(或者大于)它的父节点。
堆排序流程:
1.最大堆调整:将堆的末端子节点作调整,使子节点永远小于(或大于)父节点。
2.创建最大堆:将堆中的数据重新排序。
3.堆排序:移除位于第一个数据的根节点,并做最大堆调整的递归运算。
public class HeapSort {
public static void main(String[] args) {
int[] arr = new int[] {9, 6, 8, 7, 0, 1, 10, 4, 2};
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void heapSort(int[] arr) {
// 开始位置是最后一个非叶子节点,即最后一个节点的父节点
int start = (arr.length-2)/2;
// 调整为大顶推
for(int i = start;i>=0;i--) {
maxHeap(arr,arr.length,i);
}
//
for(int i = arr.length-1;i > 0; i--) {
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
maxHeap(arr, i, 0);
}
}
public static void maxHeap(int[] arr, int size, int index) {
// 左子节点
int leftNode = 2 * index + 1;
// 右子节点
int rightNode = 2 * index + 2;
int max = index;
// 和两个子节点分别对比,找出最大的节点
if(leftNode<size&&arr[leftNode] > arr[max]) {
max = leftNode;
}
if(rightNode<size&&arr[rightNode] > arr[max]) {
max = rightNode;
}
// 交换位置
if(max!=index) {
int temp = arr[index];
arr[index] = arr[max];
arr[max] = temp;
//交换位置后可能会破坏之前排好的堆,需要重新调整
maxHeap(arr,size,max);
}
}
}