关于二叉树的一些基本算法

1.求树高

int height(BiT bt)
{
	int hl,hr;
	if(bt==NULL)return 0;
	hl=height(bt->lchild);
	hr=height(bt->rchild);
	return (hl>hr?hl:hr)+1;
}

2.求树中(出)度为1的结点数目

int f(BiT bt)
{
	int nl,nr;
	if(bt==NULL)return 0;
	nl=f(bt->lchild);
	nr=f(bt->rchild);
	return nl+nr+(bt->lchild&&!bt->rchild||!bt->lchild&&bt->rchild);
}

(变式)求出度为2的结点数;求叶子数;求总结点数

//求出度为2的结点数
return nl+nr+(bt->lchild&&bt->rchild);
//求叶子数
return nl+nr+(!bt->lchild&&bt->rchild);
//求总结点数
return nl+nr+(bt!=NULL);

3.已知某结点指针*p,求该结点所在层号

int LayerNo(BiT bt,BiT p)
{//递归算法
	int n;
	if(bt==NULL)return 0;//树空直接返回0
	if(bt==p)return 1;//若根结点就是已知结点,则返回1
	n=LayerNo(bt->lchild,p);//向左深入
	if(n==0)n=LayerNo(bt->rchild,p);//向右深入
	if(n==0)return 0;
	return n+1;//本层递归带值返回时,应该返回n+1
}

int LayerNo(BiT bt,BiT p)
{//基于层次遍历的非递归算法,用入队元素(bt,k)表示结点bt以及其所在行号k
	int k;
	if(bt==NULL)return 0;//空树返回0
	initQueue(Q);//初始化队列
	enQueue(Q,(bt,1))//根结点入队
	while(!empty(Q))
	{
		(bt,k)=delQueue(Q);//队头元素出队
		if(bt==p)return k;//若bt即为所求,返回bt所在的行号;否则其左右儿子入队
		if(bt->lchild) enQueue(Q,(bt->lchild,k+1));
		if(bt->rchild) enQueue(Q,(bt->rchild,k+1));
	}
	return 0;//p不在该数中,返回0
}

4.已知某结点*p,求其双亲结点(类似问题:已知数值域值,在二叉树中查找结点)

  • 有返回值(返回值为求得的双亲指针)
BiT GetParent(BiT bt,BiT p)
{
	BiT parent;
	if(bt==NULL)return NULL;
	if(bt->lchild==p||bt->rchild==p)
		return bt;//若bt的左儿子或右儿子为p,则返回bt
	parent=GetParent(bt->lchild,p);//向左深入
	if(parent)return parent;
	return (GetParent(bt->rchild,p));//向右深入
}
  • 无返回值(用引用形参(C++)返回双亲指针,或用(二重)指针形参(C)返回双亲指针)
//引用形参
void GetParent(BiT bt,BiT p,BiT &parent)
{
	if(bt==NULL||parent!=NULL)return;//parent!=NULL表示结果已经求得,可以返回
	if(bt->lchild==p||bt->rchild==p) parent=bt;
	void GetParent(bt->lchild,p,parent);
	void GetParent(bt->rchild,p,parent);
}
//调用时,需进行赋初值:
BiT parent=NULL;
//pure C
void GetParent(BiT bt,BiT p,BiT *parent)
{
	if(bt==NULL||*parent!=NULL)return;//parent!=NULL表示结果已经求得,可以返回
	if(bt->lchild==p||bt->rchild==p) *parent=bt;
	void GetParent(bt->lchild,p,*parent);
	void GetParent(bt->rchild,p,*parent);
}
  • 已知数值值域
判定条件改为:
if(bt->data==p->data) result=bt;

5.求最左边的第一个叶子结点的地址

  • 基于先序遍历(先序遍历访问的第一个叶子结点即为所求)
BiT f(BiT bt)
{
	BiT result;
	if(bt==NULL) return NULL;
	if(bt->lchild==NULL&&bt->rchild==NULL) return bt;
	result=f(bt->lchild);
	if(result) return result;
	return f(bt->rchild);
}
  • 基于后序遍历(后序遍历的第一个访问节点即为所求)
BiT f(BiT bt)
{//有值返回
	BiT result;
	if(BiT==NULL) return NULL;
	result=f(bt->lchild);
	if(result) return result;
	result=f(bt->rchild);
	if(result) return result;
	return bt;
}
void f(BiT bt,BiT &p)
{//无值返回
	if(bt==NULL||p) return;
	f(bt->lchild,p);
	f(bt->rchild,p);
	if(!p) p=bt;
}

6.求中序(前序、后序)遍历第k个访问结点的指针

BiT f(BiT bt,int &k)
{//有值返回
	BiT p;
	if(bt==NULL) return NULL;
	p=f(bt->lchild,k);
	if(k>0)//或者是if(!p)
	{
		k--;
		if(k==0)return bt;
		p=f(bt->rchild,k);
	}
	return p;
}
void f(BiT bt,int &k,BiT &p)
{
	if(bt==NULL||k==0) return;
	f(bt->lchild,k,p);
	if(k>0)
	{
		k--;
		if(k==0)
		{
			p=bt;
			return;
		}
		f(bt->rchild,k,p);
	}
}

7.求某结点*p在二叉树中的访问次序
详情见求二叉树某结点在先序、中序、后序遍历中的访问次序

8.使用堆栈实现前、中、后序遍历的非递归算法

  • 先序遍历
void pretravel(BiT bt)
{
	initStack(s);
	while(bt||!emptyStack(s))
	if(bt)
	{
		visit(bt);
		push(s,bt);
		bt=bt->lchild;
	}
	else
	{
		pop(s,bt);
		bt=bt->rchild;
	}
}
  • 中序遍历
void midtravel(BiT bt)
{
	initStack(s);
	while(bt||!emptyStack(s))
	if(bt)
	{
		push(s,bt);
		bt=bt->lchild;
	}
	else
	{
		pop(s,bt);
		vist(bt);
		bt=bt->rchild;
	}
}
  • 后序遍历

需要在堆栈元素或二叉树结点中设置标志变量flag;flag=0或1表示从左或右子树返回并出栈

void lastravel(BiT bt)
{
	initStack(s);
	while(bt||!emptyStack(s))
	if(bt)//结点不空
	{
		flag=0;
		push(s,(bt,flag));//入栈
		bt=bt->lchild;//向左深入
	}
	else
	{
		pop(s,(bt,flag));/*出栈后判断标志变量(此时就是增设标志变量的意义所在:
		因为我不知道到底是从左子树返回上来的,还是从右子树返回上来的)*/
		if(flag==0)//flag==0表示已经从左子树返回,即将向右子树深入
		{
			flag=1;
			push(s,(bt,flag));
			bt=bt->rchild;
		}
		else//flag==1表示已经从右子树返回,直接访问根结点
		{
			vist(bt);
			bt=NULL;
		}
	}
}

总结:“入栈”对应递归算法中的“递归深入”,“出栈以及判断标志变量”对应递归算法中的“访问结点”

9.判断二叉树是否为完全二叉树

bool check(BiT bt,int i,int n)
{
	if(i>n)return true;
	if(bt==NULL) return false;
	return check(bt->lchild,2*i,n)&&check(bt->rchild,2*i+1,n);
}

调用时,n为结点总数(需要求得二叉树结点总数)

//调用格式
check(bt,1,n);

10.求二叉树各结点的平衡因子
为二叉链表增加一个整数域bf(balance factor)用于存放该结点的平衡因子;结点平衡因子的概念为:该结点左子树和右子树的高度差

typedef struct node
{
	ElemTp data;
	int bf;//平衡因子数值域
	struct node *lchild,*rchild;
}*BiT,BiTNode;
int f(BiT bt)
{
	int hl,hr;
	if(bt==NULL)return 0;
	hl=f(bt->lchild);
	hr=f(bt->rchild);
	bt->bf=hl-hr;//左子树高度减去右子树高度
	return (hl>hr?hl:hr)+1;
}
//该算法和求二叉树树高的算法很相似,其返回值就是树高

11.判断某一个二叉树是否是平衡二叉树
可以在算法10的基础上通过遍历每个结点的bf域,判断其绝对值是否小于等于1;或者将求树高的算法和判断是否平衡的算法综合一下

int get_bf(bt);
bool BalanceTree(BiT bt,bool &isBalanced)
{
	if(bt==NULL||!isBalanced) return false;
	if(abs(bt->bf)>1) isBalanced=false;
	if(isBalanced)
		bool(bt->lchild,isBalanced);
	if(isBalanced)
		bool(bt->rchild,isBalanced);
	return true;
}
//调用时,bool isBalanced=true;
int tst(BiT bt,bool &isBalanced)
{
	if(bt==NULL||!isBalanced) return false;
	hl=tst(bt->lchild,isBalanced);
	if(isBalanced)
	{
		hr=tst(bt->rchild,isBalanced);
		if(isBalanced)
		{
			isBalanced=abs(hl-hr)<=1;
			return max(hl,hr)+1;
		}
	}
	return false;
}
//调用时,bool isBalanced=true;
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树基本算法包括二叉树的创建、遍历和查找等操作。下面是Java语言实现二叉树基本算法的示例代码: ```java // 定义二叉树节点类 class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(int val) { this.val = val; this.left = null; this.right = null; } } // 二叉树类 class BinaryTree { private TreeNode root; public BinaryTree() { this.root = null; } // 创建二叉树 public void createBinaryTree(int[] arr) { if (arr == null || arr.length == 0) { return; } this.root = createBinaryTree(arr, 0, arr.length - 1); } private TreeNode createBinaryTree(int[] arr, int start, int end) { if (start > end) { return null; } int mid = (start + end) / 2; TreeNode root = new TreeNode(arr[mid]); root.left = createBinaryTree(arr, start, mid - 1); root.right = createBinaryTree(arr, mid + 1, end); return root; } // 前序遍历 public void preOrder() { preOrder(this.root); } private void preOrder(TreeNode root) { if (root == null) { return; } System.out.print(root.val + " "); preOrder(root.left); preOrder(root.right); } // 中序遍历 public void inOrder() { inOrder(this.root); } private void inOrder(TreeNode root) { if (root == null) { return; } inOrder(root.left); System.out.print(root.val + " "); inOrder(root.right); } // 后序遍历 public void postOrder() { postOrder(this.root); } private void postOrder(TreeNode root) { if (root == null) { return; } postOrder(root.left); postOrder(root.right); System.out.print(root.val + " "); } // 查找节点 public TreeNode search(int val) { return search(this.root, val); } private TreeNode search(TreeNode root, int val) { if (root == null || root.val == val) { return root; } TreeNode left = search(root.left, val); if (left != null) { return left; } return search(root.right, val); } } // 测试代码 public class Main { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5, 6, 7}; BinaryTree binaryTree = new BinaryTree(); binaryTree.createBinaryTree(arr); System.out.print("前序遍历:"); binaryTree.preOrder(); System.out.println(); System.out.print("中序遍历:"); binaryTree.inOrder(); System.out.println(); System.out.print("后序遍历:"); binaryTree.postOrder(); System.out.println(); System.out.println("查找节点 4:" + binaryTree.search(4).val); } } ``` 输出结果为: ``` 前序遍历:4 2 1 3 6 5 7 中序遍历:1 2 3 4 5 6 7 后序遍历:1 3 2 5 7 6 4 查找节点 4:4 ``` 以上代码实现了二叉树的创建、前序遍历、中序遍历、后序遍历和查找节点基本算法。其中,创建二叉树使用了二分法,遍历使用了递归方式实现,查找节点使用了递归方式和回溯思想实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值