到难点了,个人认为初阶数据结构最难的点就在于二叉树,所以我尽量写的详细,清楚一些
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。这种结构类似于一颗大树的成长。首先是一个结点,树成长了,形成了几个叶子,而这几个叶子也将成为这个枝干的结点。只不过这是自然界的树,在计算机数据结构中,这颗树是倒着这的。
树
这个图树一个比较特殊的树,名字叫二叉树
这个机构我先提出几个问题:
答:
规定:
二叉树又分为。满二叉树和完全二叉树。
满二叉树:及每个结点的子结点个数都为2,也就是满的
百度定义:
满二叉树: 一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为K,且结点总数是 2^k-1,则它就是满二叉树。
———————————————————————————————————————————
完全二叉树:具有二叉树性质的,最差满足左树的二叉树。也就是说,无需去理会是否同时具有左树和右树的情况(满足这个情况的其实是满二叉树),但必须满足左树存在的情况。
百度定义:
完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应时称之为完全二叉树。
注意:
是满二叉树是一种特殊的完全二叉树。
对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有:
若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
(1):若2i+1
(2):若2i+2
二叉树的存储结构分为:顺序存储(下面回仔细讲解(堆排序))和类似于链表(这里将实现)的链式存储
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}
双叉树的遍历分为3种: 前序遍历,中序遍历,后序遍历
前序遍历:访问根结点—>根的左子树—>根的右子树
static class TreeNode {
public char val;
public TreeNode left;//左孩子的引用
public TreeNode right;//右孩子的引用
public TreeNode(char val) {
this.val = val;
}
}
/**
* 创建一棵二叉树 返回这棵树的根节点
*
* @return
*/
public TreeNode root=null;
public TreeNode createTree() {
TreeNode root=null;
return root;
}
// 前序遍历
public void preOrder(TreeNode root) {
if (root==null) {
return;
}
//先访问根结点的数据
System.out.println(root.val);
//在访问左子字节点的数据
preOrder(root.left);
//最后访问右子结点的数据
preOrder(root.right);;
}
前序遍历
中序遍历:根的左子树—>根节点—>根的右子树。
static class TreeNode {
public char val;
public TreeNode left;//左孩子的引用
public TreeNode right;//右孩子的引用
public TreeNode(char val) {
this.val = val;
}
}
/**
* 创建一棵二叉树 返回这棵树的根节点
*
* @return
*/
public TreeNode root=null;
public TreeNode createTree() {
TreeNode root=null;
return root;
}
//中序遍历
void inOrder(TreeNode root) {
if (root==null) {
return;
}
//先遍历左字节点
inOrder(root.left);
//再遍历根节点
System.out.println(root.val);
//最后遍历右结点
inOrder(root.right);;
}
中序遍历
后序遍历:根的左子树—>根的右子树—>根节点。
static class TreeNode {
public char val;
public TreeNode left;//左孩子的引用
public TreeNode right;//右孩子的引用
public TreeNode(char val) {
this.val = val;
}
}
/**
* 创建一棵二叉树 返回这棵树的根节点
*
* @return
*/
public TreeNode root=null;
public TreeNode createTree() {
TreeNode root=null;
return root;
}
// 后序遍历
void postOrder(TreeNode root) {
if (root==null) {
return;
}
//先访问左树的数据
postOrder(root.left);
//再访问右树的数据
postOrder(root.right);
//最后访问根的数据
System.out.println(root.val);
}
后序遍历
层序遍历:从左往右依次遍历
//层序遍历
public void levelOrder(TreeNode root){
if (root==null){
return;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
TreeNode cur=queue.poll();
System.out.print(cur.val+"");
if (cur.left!=null){
queue.offer(cur.left);
}
if (cur.right!=null){
queue.offer(cur.right);
}
}
}
到了这里,其实大家对于二叉树的结构已经较为了解了,接下来,大家可以尝试书写一下我所实现的功能。真没心力去做视频了。等我回复一点血,在讲解下面的代码。求求了。。。。,我好像挖了不少的坑。。。。
public class TestBinaryTree {
static class TreeNode{
public char val;//数据域
public TreeNode left;//左孩子
public TreeNode right;//右孩子
public TreeNode(char val){
this.val=val;
}
}
public TreeNode root;//二叉树的根节点
public void createTree(){
}
//前序遍历
public void preOrder(TreeNode root){
if (root==null){
return;
}
System.out.println(root.val+"");
preOrder(root.left);
preOrder(root.right);
}
public List<Character> preorderTraversal(TreeNode root) {
List<Character> ret=new ArrayList<>();
if (root==null){
return null;
}
ret.add(root.val);
List<Character> leftret= preorderTraversal(root.left);
leftret.addAll(leftret);
List<Character> rightret= preorderTraversal(root.left);
leftret.addAll(rightret);
return ret;
}
// 中序遍历
public void inOrder(TreeNode root){
if (root==null){
return;
}
inOrder(root.left);
System.out.println(root.val+"");
inOrder(root.right);
}
// 后序遍历
public void postOrder(TreeNode root){
if (root==null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.println(root.val+"");
}
// 获取树中节点的个数
public int size(TreeNode root){
if (root==null){
return 0;
}
int leftSize=size(root.left);
int rightSize=size(root.right);
return leftSize+rightSize+1;
}
// 获取叶子节点的个数
public int getLeafNodeCount(TreeNode root){
if (root==null){
return 0;
}
if (root.left==null&&root.right==null){
return 1;
}
int leftroot=getLeafNodeCount(root.left);
int rightroot=getLeafNodeCount(root.right);
return leftroot+rightroot;
}
// 子问题思路-求叶子结点个数
// 获取第K层节点的个数
public int getKLevelNodeCount(TreeNode root,int k){
if (root==null){
return 0;
}
if (k==1){
return 1;
}
int leftSzie= getKLevelNodeCount(root.left,k-1);
int rightSize= getKLevelNodeCount(root.right,k-1);
return leftSzie+rightSize;
}
// 获取二叉树的高度
public int getHeight(TreeNode root){
if (root==null){
return 0;
}
int rightSzie =getHeight(root.right);
int leftSzie=getHeight(root.left);
if (rightSzie>=leftSzie){
return rightSzie+1;
}else {
return leftSzie+1;
}
}
// 检测值为value的元素是否存在
public TreeNode find(TreeNode root, int val){
if (root==null){
return null;
}
if (root.val==val){
return root;
}
TreeNode leftTree=find(root.left, val);
if (leftTree!=null){
return leftTree;
}
TreeNode rightTree=find(root.right, val);
if (rightTree!=null){
return rightTree;
}
return null;
}
//层序遍历
public void levelOrder(TreeNode root){
if (root==null){
return;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
TreeNode cur=queue.poll();
System.out.print(cur.val+"");
if (cur.left!=null){
queue.offer(cur.left);
}
if (cur.right!=null){
queue.offer(cur.right);
}
}
}
// 判断一棵树是不是完全二叉树
public boolean isCompleteTree(TreeNode root){
if (root==null){
return false;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
TreeNode cur= queue.poll();
if (cur!=null){
queue.offer(cur.left);
queue.offer(cur.right);
}else {
break;
}
}
while (!queue.isEmpty()){
TreeNode tmp=queue.poll();
if (tmp!=null){
return false;
}
}
return true;
}
}
文章链接
文章链接
文章链接
文章链接
文章链接
文章链接
文章链接
文章链接
HashMap和HashSet,TreeMap和TreeSet
文章链接
里面有堆排序的实现和逻辑
文章链接
文章链接
文章链接