二叉树

一、二叉树相关的概念

 树(tree)是n(n>=0)个结点的有限集。n=0时称为空树。在任何一棵非空树中:

(1)有且仅有一个特定的成为根的结点(root);

(2)当n>1时,其余结点可分为m(m<0)个互不相交的有限集T1、T2、……、Tm,其中每一个集合本身又是一棵树,并且称为根的子树,如下图所示:


结点拥有的子树称为结点的度;

度为0的结点称之为叶子节点或终端结点;

树的度是树内各节点度的最大值;

树中结点的最大层次称为树的深度或高度,上图树的深度为4。

二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者空集(称为空二叉树),或者有一个根结点和两颗互不相交的、分别称为根结点的左子树和右子树的二叉树组成。上图就是一颗二叉树。

二、二叉树的相关代码

(1)二叉树结点定义如下:

typedef char ElemType;

typedef struct BTnode
{
	ElemType data;    //数据域
	BTnode *leftchild;    //左孩子指针
	BTnode *rightchild;    //右孩子指针
}BTnode;

(2)申请一个结点、释放一个结点代码如下:

BTnode *buynode()    //申请
{
	BTnode *p = (BTnode *)malloc(sizeof(BTnode));
	if (p == NULL)
		exit(1);
	memset(p, 0, sizeof(BTnode *));
	return p;
}

void freeNode(BTnode *ptr)    //释放
{
	free(ptr);
}

(3)创建一颗二叉树的代码如下:

BTnode * create_tree(ElemType *&str)    //利用参数创建二叉树
{
	BTnode *s = NULL;
	if (str!=NULL && *str!=END)
	{
		s = buynode();
		s->data = *str;
		s->leftchild = create_tree(++str);
		s->rightchild = create_tree(++str);
	}
	return s;
}

BTnode *create_tree2()    //无参数,手动输入创建二叉树
{
	BTnode *s = NULL;
	ElemType item;
	cin >> item;
	
	if (item != END)
	{
		s = buynode();
		s->data = item;
		s->leftchild = create_tree2();
		s->rightchild = create_tree2();
	}

	return s;
}

(4)二叉树的三种递归遍历(前序、中序和后序)

void preorder(BTnode *ptr)    //前序
{
	if (ptr != NULL)
	{
		cout << ptr->data << " ";
		preorder(ptr->leftchild);
		preorder(ptr->rightchild);
	}
}

void inorder(BTnode *ptr)    //中序
{
	if (ptr != NULL)
	{
		inorder(ptr->leftchild);
		cout << ptr->data << " ";
		inorder(ptr->rightchild);
	}
}

void lastorder(BTnode *ptr)    //后续
{
	if (ptr != NULL)
	{
		lastorder(ptr->leftchild);
		lastorder(ptr->rightchild);
		cout << ptr->data << " ";
	}
}

(5)二叉树的三种非递归遍历(前序、中序和后序)

void NicePreOrder(BTnode *ptr)    //前序
{
	if (ptr == NULL) return ;
	stack<BTnode *> st;
	st.push(ptr);
	while (!st.empty())
	{
		ptr = st.top(); st.pop();
		cout << ptr->data << " ";
		if (ptr->leftchild != NULL)
		{
			st.push(ptr->leftchild);
		}
		if (ptr->rightchild != NULL)
		{
			st.push(ptr->rightchild);
		}
	}
	cout << endl;
}

void NiceInOrder(BTnode *ptr)    //中序
{
	if (ptr == NULL) return ;
	stack<BTnode *> st;
	while (!st.empty() || ptr!=NULL)
	{
		while (ptr != NULL)
		{
			st.push(ptr->leftchild);
			ptr = ptr->leftchild;
		}
		ptr = st.top(); st.pop();
		cout << ptr->data << " ";
		ptr = ptr->rightchild;
	}
	cout << endl;
}

void NicePastOrder(BTnode *ptr)    //后序
{
	if (ptr == NULL) return ;
	stack<BTnode *> st;
	BTnode *tag = NULL;
	while (!st.empty() || ptr!=NULL)
	{
		while (ptr != NULL)
		{
			st.push(ptr);
			ptr = ptr->leftchild;
		}
		ptr = st.top(); st.pop();
		if (ptr->rightchild==NULL || ptr->rightchild==tag)
		{
			cout << ptr->data << " ";
			tag = ptr;
			ptr = NULL;
		}
		else
		{
			st.push(ptr);
			ptr = ptr->rightchild;
		}
	}
	cout << endl;
}

(6)求二叉树的结点个数代码如下:

int size_tree(BTnode *ptr)
{
	if (ptr == NULL) return 0;
	return size_tree(ptr->leftchild)+size_tree(ptr->rightchild)+1;
}

(7)求二叉树的深度代码如下:

int depth_tree(BTnode *ptr)//二叉树的深度
{
	if (ptr == NULL) return 0;
	int left = depth_tree(ptr->leftchild);
	int right = depth_tree(ptr->rightchild);
	return left>right?left+1:right+1;
}

(8)判断是否为满二叉树代码如下:

满二叉树:在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。如下图所示:


bool Is_Full_BinaryTree(BTnode *ptr)    //数学方法判断
{
	int sum = size_tree(ptr);
	int depth = depth_tree(ptr);
	return (pow(2.0, depth)-1) == sum;
}

bool Is_Full_BinaryTree2(BTnode *ptr)    //递归的方法创建
{
	return (ptr==NULL) 
		|| (
		ptr!=NULL
		&& Is_Full_BinaryTree2(ptr->leftchild) 
		&& Is_Full_BinaryTree2(ptr->rightchild)
		&& depth_tree(ptr->leftchild)==depth_tree(ptr->rightchild)
		);
}

(9)打印二叉树的第K层元素,代码如下:

void Print_K_Level_Item(BTnode *ptr, int k)
{
	if (ptr==NULL || k<0) 
		return ;
	else if(k == 0)
	{
		cout << ptr->data << " ";
	}
	else
	{
		Print_K_Level_Item(ptr->leftchild, k-1);
		Print_K_Level_Item(ptr->rightchild, k-1);
	}
}

(10)层次遍历二叉树(递归和非递归),代码如下:

void LevelOrder(BTnode *ptr)    //递归
{
	if (ptr == NULL) return ;
	int level = depth_tree(ptr);
	for (int k=0; k<level; k++)
	{
		Print_K_Level_Item(ptr, k);
	}
	cout << endl;
}

void NiceLevelOrder(BTnode *ptr)
{
         if (ptr == NULL) return ;
         queue<BTnode *> qu;
         qu.push(ptr);
         while (!qu.empty())
         {
                  ptr = qu.front(); qu.pop();
                  cout << ptr->data << " ";
                  if (ptr->leftchild != NULL)
                  {
                           qu.push(ptr->leftchild);
                  }
                  if (ptr->rightchild != NULL)
                  {
                           qu.push(ptr->rightchild);
                  }
         }
         cout << endl;
}

(11)寻找parent结点,代码如下:

BTnode *Parent(BTnode *ptr, BTnode *child)
{
         if (ptr==NULL || ptr->leftchild==NULL || ptr->rightchild==NULL)
                  return ptr;
         else
         {
                  BTnode *p = Parent(ptr->leftchild, child);
                  if (p == NULL)
                  {
                           p = Parent(ptr->rightchild, child);
                  }
                  return p;
         }
}

BTnode *FindParent(BTnode *ptr,BTnode *child)
{
         if (ptr==NULL || child==NULL) return NULL;
         else
         {
                  return Parent(ptr, child);
         }
}

(12)前序和中序构建二叉树、后序和中序构建二叉树(已知前序和后序不能确定一棵树),代码如下:

int Findls(ElemType *is, int n, ElemType x)    //找到X在数组中的位置
{
	int pos = -1;
	for (int i=0; i<n; ++i)
	{
		if (is[i] == x)
		{
			pos = i;
			break;
		}
	}
	return pos;
}

BTnode *create_treePI(ElemType *ps, ElemType *is, int n)    //前序和中序构建二叉树
{
	BTnode *s = NULL;
	if (ps!=NULL && is!=NULL && n>0)
	{
		s = buynode();
		s->data = ps[0];
		int pos = Findls(is, n, ps[0]);
		if(pos == -1) exit(1);
		s->leftchild = create_treePI(ps+1, is, pos);
		s->rightchild = create_treePI(ps+pos+1, is+pos+1, n-pos-1);
	}
	return s;
}

BTnode *create_treeIL(ElemType *is, ElemType *ls, int n)    //中序和后续构建二叉树
{
	BTnode *s = NULL;
	if (is!=NULL && ls!=NULL && n>0)
	{
		s = buynode();
		s->data = ls[n-1];
		int pos = Findls(is, n, ls[n-1]);
		if (pos == -1) exit(1);
		s->leftchild = create_treeIL(is, ls, pos);
		s->rightchild = create_treeIL(is+pos+1, ls+pos, n-pos-1);
	}
	return s;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值