一、二叉树介绍
二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
二、顺序二叉树
利用数组实现顺序二叉树,数组的一个元素不参与二叉树,依此将数组元素摆放到左右子树上。
三、顺序二叉树实现堆排序
1.堆排序介绍
堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。
2.过程
1)初始化一个总长度变量。
2)只要这个变量大于2,就是至少一个父节点的情况(这里数字第一个元素不参与二叉树排列)
3)从最后一个父节点开始遍历每个父节点,比较它和自己最大的孩子,如果最大孩子大于自己,跟自己交换
4)根节点和最后一个节点交换位置
5)重复3-4,每次重复第一步的总长度变量减一
3. 实现
public class HeapSort {
// 数组实现顺序二叉树
// 数组第一个元素不参与二叉树,第二个元素作为二叉树的根节点
// 父节点个数为(数组长度-1)/2
// 父节点下标 1~父节点个数
// 子节点下标
// 左子树为父节点下标*2
// 右子树为左子树下标+1
// 利用二叉树实现堆排序
// 1.从下到上比较,从右到左比较
// 2.比较左右孩子,最大的孩子跟父节点比较,如果最大孩子大于父节点,最大孩子跟父节点交换位置
public static void main(String[] args) {
int[] ints = {0, 6, 2, 8, 1, 5, 4, 9, 3};
// 这里通过一个变量来记录最后的节点数
int end = ints.length;
//这里考虑数组大于2的情况,就表示有父节点。只有2个元素,就是只有一个根节点了。
while (end > 2) {
//父节点个数=(数组长度-1)/2;父节点索引=1到父节点个数
//循环遍历所有的父节点(从最后一个父节点开始遍历),
for (int i = (end - 1) / 2; i >= 1; i--) {
//左儿子索引=父节点索引*2,右儿子索引=左儿子+1
//根据父节点索引计算2个儿子的索引,找到2个儿子中最大的儿子
int maxIndex = 2 * i;
//只有右孩子下标小于数组长度 并且右孩子大于左节点,最大孩子下标为右孩子
if ((maxIndex + 1) < end && ints[maxIndex + 1] > ints[maxIndex]) {
maxIndex++;
}
//如果最大孩子大于父节点,两者交换位置
if (ints[maxIndex] > ints[i]) {
ints[maxIndex] = ints[maxIndex] ^ ints[i];
ints[i] = ints[maxIndex] ^ ints[i];
ints[maxIndex] = ints[maxIndex] ^ ints[i];
}
}
//将根节点和最后一个节点交换位置
ints[1] = ints[1] ^ ints[end - 1];
ints[end - 1] = ints[1] ^ ints[end - 1];
ints[1] = ints[1] ^ ints[end - 1];
//每循环一次,最后一个数的位置向前移动一位
end--;
}
for (int i : ints) {
System.out.println(i);
}
}
}
4.时间复杂度
平均时间复杂度为:O(nlogn)
5.空间复杂度:
平均时间复杂度为:O(1)
6.稳定性
不稳定
四、链式二叉树及三种遍历方式
0.节点定义
public class Node {
//节点值
int value;
//左子树
Node left;
//右子树
Node right;
public Node(int value){
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
1.新增节点
//定义根节点
Node root;
//增加节点
public void add(int value) {
Node newNode = new Node(value);
//如果根节点为空,则根节点等于该新节点
if (root == null) {
root = newNode;
} else {
// 复制根节点
Node tmp = root;
//否则判定根节点与新节点的值比较,小于插入左边,大于插入右边
while (true) {
//小的在左边
if (value < tmp.getValue()) {
if (tmp.getLeft() == null) {
tmp.setLeft(newNode);
break;
} else {
tmp = tmp.getLeft();
}
}else {
//大的在右边
if(tmp.getRight() == null){
tmp.setRight(newNode);
break;
}else{
tmp = tmp.getRight();
}
}
}
}
}
2.遍历节点
//查找某个节点
public void show(){
showNode(root);
}
private void showNode(Node node){
//前序遍历
// System.out.println(node.getValue());
if(node.getLeft() != null){
showNode(node.getLeft());
}
//中序遍历
// System.out.println(node.getValue());
if(node.getRight() != null){
showNode(node.getRight());
}
//后续遍历
System.out.println(node.getValue());
}
参考:
二叉树百科