java数据结构和算法④——树论基础和归并排序

树论基础

树是数据结构和算法分析与设计中的一种非常重要的结构,由N个节点组成的
具有层次结构的模型。其主要有以下几个特点:

  • 有一个根节点,一般称为root节点
  • 每一个元素都被称为node
  • 除了root节点外,其余的节点都会被分成n个互不相交的集合,子树。

在这里插入图片描述

树形结构里面的基本术语:

  • 结点:树形结构里面的元素
  • 子树:当结点大于1时,其余的结点分为的互不相交的集合称为子树
  • :一个结点拥有的子树数量称为结点的度
  • 叶子:度为0的结点
  • 孩子:结点的子树的根称为孩子结点
  • 双亲:和孩子结点对应
  • 兄弟:同一个双亲结点
  • 深度:结点的最大层次称为树的深度,计算时间复杂度用
  • 森林:由N个互不相交的树构成深林

二叉树

二叉树(Binary Tree):一种特殊的树形结构,每个节点至多只有两颗子树

下面的除了1都属于二叉树
在这里插入图片描述
在二叉树的第N层上至多有2^(N-1)个结点。最多有2^N-1个结点个数

满二叉树(完全二叉树):假设树的深度为M,其有2^M-1个jie点的二叉树,假如深度为3,那么就有2^3 – 1 =7个结点的就是。上图的3号树就是满二叉树。

具有N个结点的完全二叉树其深度为log2^n +1,注意这个特性决定了索引树的时间复杂度。

二叉树的三种遍历
  • 前序遍历
    根节点(输出自身)→左子树→右子树
  • 中序遍历
    左子树→根节点(输出自身)→右子树
  • 后序遍历
    左子树→右子树→根节点(输出自身)

假设有如下的二叉树
在这里插入图片描述
中序遍历的具体过程如下

中序遍历:左子树 根节点(输出)右子树
遍历都是从根结点开始:
首先到A,A的左子树存在,找到B。
把B看成子树,找B的左,没有返回B,记录B。
找B右,找到C,又把c看成子树,
找C的左,找到D。记录D,此时D没有了,我
们返回C,再找跟,记录C
入度:为0就是根
出度:为0叶子
BDCAEHGKF

前序遍历为ABCDEFGHK

后序遍历为DCBHKGFEA

具体代码如下

class Node{
	private char data;
	private Node leftNode;
	private Node rightNode;
	public Node(char data, Node leftNode, Node rightNode) {
		super();
		this.setData(data);
		this.setLeftNode(leftNode);
		this.setRightNode(rightNode);
	}

	public char getData() {
		return data;
	}

	public void setData(char data) {
		this.data = data;
	}

	public Node getLeftNode() {
		return leftNode;
	}

	public void setLeftNode(Node leftNode) {
		this.leftNode = leftNode;
	}

	public Node getRightNode() {
		return rightNode;
	}

	public void setRightNode(Node rightNode) {
		this.rightNode = rightNode;
	}
	
}

public class BinaryTree {
	
	public static void main(String[] args) {
		Node D = new Node('D', null, null);
		Node H = new Node('H', null, null);
		Node K = new Node('K', null, null);
		Node C = new Node('C', D, null);
		Node B = new Node('B', null, C);
		Node G = new Node('G', H, K);
		Node F = new Node('F', G, null);
		Node E = new Node('E', null, F);
		Node A = new Node('A', B, E);		//就是root结点
		
		BinaryTree binaryTree = new BinaryTree();
		System.out.println("前");
		binaryTree.pre(A);
		System.out.println("中");
		binaryTree.in(A);
		System.out.println("后");
		binaryTree.post(A);
		
	}
	
	public void print(Node node) {
		System.out.print(node.getData());
	}
	
	public void pre(Node root) {		//前序遍历 根节点 (输出) 左子树  右子树
		print(root);
		if(root.getLeftNode() != null) {
			pre(root.getLeftNode());
		}
		if(root.getRightNode() != null) {
			pre(root.getRightNode());
		}
	}
	
	public void in(Node root) {		//中序遍历  左子树 根节点 (输出)  右子树
		if(root.getLeftNode() != null) {
			pre(root.getLeftNode());
		}
		print(root);
		if(root.getRightNode() != null) {
			pre(root.getRightNode());
		}
	} 
	public void post(Node root) {		//中序遍历  左子树   右子树 根节点 (输出)
		if(root.getLeftNode() != null) {
			pre(root.getLeftNode());
		}
		if(root.getRightNode() != null) {
			pre(root.getRightNode());
		}
		print(root);
	}
}

归并排序

归并排序的流程示意图如下,分为分开和合并两个过程。在合并的过程中,只需要对两个数列的头作比较就可以了,因为数列本身就已经时排过序的了,所以整个过程很快速
在这里插入图片描述
具体代码如下

public class MergSort {
	public static void main(String[] args) {
		int data[] = {9,5,6,8,0,3,7,1,20,1};
		mergeSort(data, 0, data.length -1);
		System.out.println(Arrays.toString(data));
	}
	
	public static void mergeSort(int data[],int left,int right) {
		if(left <  right) {
			int mid = (left + right) / 2;
			mergeSort(data, left, mid);
			mergeSort(data, mid+1, right);
			//以上就分完了
			merge(data, left, mid, right);
		}
	}
	
	public static void merge(int data[],int left,int mid,int right) {
		int temp[] = new int[data.length];		//就是用来保存合并后的序列,辅助我们排序
		
		int point1 = left;	//表示左边的第一个数的位置
		int point2 = mid + 1;	//表示后边的第一个数的位置
		
		int loc = left;	//这个就是用来保存我们当前填了那个数字到temp里面去
		while(point1 <= mid && point2 <= right) {
			if(data[point1] <= data[point2]) {
				temp[loc] = data[point1];
				loc ++ ;
				point1 ++ ;
			}else {
				temp[loc] = data[point2];
				loc ++ ;
				point2 ++ ;
			}
		}
		while(point1 <= mid) {
			temp[loc++] = data[point1++];
		}
		while(point2 <= right) {
			temp[loc ++] = data[point2 ++];
		}
		for(int i = left ;i <= right ; i++) {
			data[i] = temp[i];
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值