二叉树的基本操作

原创 2018年04月15日 19:22:33

 在学习数据结构的时候学完栈、队列之后下一个比较难、比较重要的就是树。它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:每个节点有零个或多个子节点;没有父节点的节点称为根节点;每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树。

这是百度的一个词条介绍,一点都不通俗易懂

 

这就是一个抽象出来的通俗易懂的树的结构图,不过这是一种特殊的树的结构,也是今天我所要操作的树-------二叉树。其实二叉树很好理解,二叉树的每个结点至多只有二棵子树(不存在度大于2的结点)

这是一些树的相关术语,如果之前没听过树的话,可以简单了解一下

树的结点:包含一个数据元素及若干指向子树的分支;

孩子结点:结点的子树的根称为该结点的孩子;

双亲结点:B 结点是A 结点的孩子,则A结点是B 结点的双亲;

兄弟结点:同一双亲的孩子结点;

祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙

树的深度:树中最大的结点层

树的度: 树中最大的结点度。

叶子结点:也叫终端结点,是度为 0 的结点;

对这些概念有一个简单的了解就可以。

今天我们就来通过代码创建一个二叉树。今天主要实现的函数有,二叉树的创建,二叉树的三种遍历方式,二叉树的中的结点个数,二叉树中叶子节点的个数,二叉树第K层的叶子结点个数。

首先我们先通过画图软件来画出我们今天要实现的二叉树的抽象图。

 

然后将他转化成一个数组int a[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6, '#', '#', '#' };

这是这个二叉树先序遍历的数组,如果下边没有结点是空的话,那就用 '#'来表示。

 

typedef int BTDataType;

 

typedef struct BinaryTreeNode

{

struct BinaryTreeNode* _left;

struct BinaryTreeNode* _right;

BTDataType _data;

}BTNode;

 

 

BTNode* BuyBTNode(BTDataType x)

{

BTNode *Node =(BTNode*) malloc(sizeof(BTNode));

Node->_data = x;

Node->_left = NULL;

Node->_right = NULL;

return Node;

}

这是在创建二叉树之前的创建的二叉树结构体,以及给二叉树的空间分配函数。二叉树中包括你的左孩子指针,右孩子指针,以及你当前结点的数值。

 

BTNode* CreateBTree(BTDataType* a, size_t* pIndex, BTDataType invalid)

{

assert(a);

if (a[*pIndex] == invalid)

return NULL;

BTNode *root = BuyBTNode(a[*pIndex]);

++(*pIndex);

root->_left=CreateBTree(a, pIndex, invalid);

++(*pIndex);

root->_right=CreateBTree(a, pIndex, invalid);

return root;

 

 

}

之后是创建二叉树的函数,这里传入了三个参数,第一个是我们取值的数组,通过数组中的值来个二叉树中的结点赋值,pIndex是来访问的数组下标位置,正常的话我们这里传入一个数字就行,为什么要传入一个指针呢?因为看我们的程序,如果你传入的是一个数值。

root->_left=CreateBTree(a, Index++, invalid);这里写成这样,想一下,递归有什么特点?递归是在栈上进行的,栈大家也都清楚,在你当前函数运行结束之后,栈是会进行销毁的,但是你的数组可以一直进行下去的,通过图和数组对比也可以看到1的右孩子5的数组下标已经是8了。有的人说可以将你的index设置成全局或者说静态变量,这种方法在当前阶段也是可取的,但是当你存在多线程的时候全局变量就很容易受到其他线程的影响,导致程序出现一些bug所以这里我们传了指针。第三个参数是invalld也就是非法制也就是你的二叉树的结束值,这里在当前状态下也是可以不传的,但是当前的结束值是'#'如果以后改动的话还是传入一个参数比较方便控制。

  这里创建二叉树的函数代码十分简单就是将你当前结点和你的左右孩子结点链接起来就可以了。通过递归来实现最后返回你当前的根节点。

void BTreePrevOrder(BTNode* root)

{

if (root == NULL)

return;

else

{

printf("%d", root->_data);

BTreePrevOrder(root->_left);

BTreePrevOrder(root->_right);

 

}

}

先序遍历和中序遍历以及后序遍历的代码只是顺序的区别,所以这里我就只介绍一个先序中序后序遍历分别是什么。

 

通过这个图来介绍,这里的先中后指的是你的根节点的顺序,也就是说,如果是先序遍历,你当前在2位置,那就直接输出2然后再去遍历他的左孩子,右孩子,也就是234,如果要是中序遍历也就是虽然你当前在2位置但是不输出当前数据,会先遍历他的左孩子,然后中序遍历根节点就在中间,之后才是右孩子,所以顺序会是324,如果要是后序遍历,代表着你当前的结点在最后边,也就是先遍历左孩子右孩子然后才是根节点,这里的顺序是342.

 

如果说这个图的先序遍历,那就是123456,遇到1输出,然后遍历他的左孩子,遇到2输出,然后遇到他的左孩子3输出,下边没孩子,然后返回2,去遍历2的右孩子遇到4输出,然后再返回2,之后开始遍历1的右孩子。

在简单介绍一下这个图的后序遍历,遇到1先不输出往他的左孩子走,走到2,2还有左孩子继续走,走到3,没有左右孩子,直接输出3,然后返回2继续不输出去遍历2的右孩子,4输出,然后返回2之后,再到1,1的右孩子还没有输出所以不能输出1,开始遍历1的右孩子5,因为5有左孩子那就遍历6输出6,返回5去遍历5的右孩子是空返回来,然后输出5,最后返回1输出。后序遍历的顺序就是342651

void BTreeInOrder(BTNode* root)//中序遍历

{

if (root == NULL)

return;

else

{

BTreeInOrder(root->_left);

printf("%d", root->_data);

BTreeInOrder(root->_right);

 

}

}

void BTreePostOrder(BTNode* root)//后序遍历

{

if (root == NULL)

return;

else

{

BTreePostOrder(root->_left);

BTreePostOrder(root->_right);

printf("%d", root->_data);

 

}

}

 

size_t BTreeSize(BTNode* root)

{

if (root == NULL)

return 0;

else

return 1 + BTreeSize(root->_left) + BTreeSize(root->_right);

}

这是用来求二叉树中结点的个数,其实二叉树的基本操作要掌握一个关键词那就是递归,二叉树中用递归来实现程序是一个很方便的。对于这个求节点数,也是一样的,你当前数的结点数就是你当前结点1,加上你的左孩子的结点数,加上你的右孩子的结点数,这个子问题不断的向下扩展,一直到root是空的时候开始返回。

size_t BTreeLeafSize(BTNode* root)

{

if (root == NULL)

return 0;

if ((root->_left== NULL) && (root->_right == NULL))

return 1;

return BTreeLeafSize(root->_left) + BTreeLeafSize(root->_right);

}

size_t BTreeKLevelSize(BTNode* root, size_t k)

{

if (root == NULL)

{

return 0;

}

if (k == 1)

{

return 1;

}

return BTreeKLevelSize(root->_left, k - 1) + BTreeKLevelSize(root->_right, k - 1);

}

这两个分别是当前树的叶子结点数,以及树第K层。同样还是递归思想来实现,你的结点是你左孩子的叶子结点个数加上右孩子的叶子结点可数,一直划分下去的子问题。

void TestBinaryTree()

{

int a[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6, '#', '#', '#' };

size_t index = 0;

BTNode* tree = CreateBTree(a, &index, '#');

BTreePrevOrder(tree);

printf("\n");

BTreeInOrder(tree);

printf("\n");

BTreePostOrder(tree);

printf("\n");

 

printf("BTreeSize%d\n", BTreeSize(tree));

printf("BTreeLeafSize%d\n", BTreeLeafSize(tree));

printf("BTreeKLevelSize?%d\n", BTreeKLevelSize(tree, 2));

}

 


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hanani_Jia/article/details/79952064

总把新桃换旧符

总把新桃换旧符——写在《最后期限》出版之前上个星期,《最后期限》的编辑给我一个电话,告诉我这本书在本周内就会生产出来了,让我颇感欣慰。从8月以来,心情一直不好,在上海与CSDN网友见面之后也没有什么特...
  • gigix
  • gigix
  • 2002-12-26 15:28:00
  • 2397

二叉树第k层的叶子节点数

不论是“求二叉树第k层的节点数”还是“求二叉树第k层的叶子节点数”,算法思想都是二叉树的层序遍历,在前面几篇博文中已经多次讲述,此处就不再赘述了。求二叉树第k层的叶子节点数,同样有递归方法和非递归方法...
  • cyuyanenen
  • cyuyanenen
  • 2016-06-03 21:31:25
  • 1141

求解二叉树第K层节点数目

求解二叉树第K层节点数目,使用递归解法,第k层的节点数=第k-1层左孩子节点数+第k-1层右孩子节点数目,直到k==1时,说明已经到了第K层。 非递归实现二叉树的第K层节点数目,需要借助队列,与求解二...
  • jcm666666
  • jcm666666
  • 2016-09-16 11:28:25
  • 1600

求二叉树叶子节点的个数和第k层的节点个数【每日一题】

1.求二叉树中叶子节点的个数 (1)如果二叉树为空,返回0 ; (2)如果二叉树不为空且左右子树为空,返回1; (3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树...
  • gaoruxue918
  • gaoruxue918
  • 2017-07-22 12:01:07
  • 139

求二叉树叶子节点的个数/求二叉树第k层的节点个数

int FindLeavesOfBinaryTree(BinaryTreeNode* pRoot) //求二叉树叶子结点的个数 { if (pRoot == NULL) ret...
  • dcjhyn
  • dcjhyn
  • 2017-07-24 21:33:55
  • 171

二叉树第K层叶子节点个数 -- 采用递归和非递归方法实现

/*二叉树第K层叶子节点个数 -- 采用递归和非递归方法 经调试可运行源码及分析如下: ***/ #include #include #include using std::cout; using...
  • y396397735
  • y396397735
  • 2016-04-14 17:06:33
  • 383

二叉树(8)----求二叉树第K层的节点数和二叉树第K层的叶子节点数,递归方式和非递归方式

1、二叉树定义 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct ...
  • beitiandijun
  • beitiandijun
  • 2014-12-15 11:12:40
  • 5157

求二叉树中叶子节点个数,总的节点个数,第K层的节点个数

struct BinaryTree { char value; BinaryTree* left; BinaryTree* right; }; //求二叉树中的节点个数 //(1)如果二叉树为...
  • zheng0518
  • zheng0518
  • 2013-05-08 16:24:50
  • 2833

二叉树中叶子节点的个数第K层的节点个数

叶子节点的个数size_t _GetLeefNode(Node *pRoot) { if (pRoot == NULL) return 0; if (NULL == p...
  • gjggj
  • gjggj
  • 2017-07-29 22:13:16
  • 257

六:二叉树中第k层节点个数与二叉树叶子节点个数

二叉树中第k层节点个数 递归解法: (1)如果二叉树为空或者k1,返回左子树中k-1层的节点个数与右子树k-1层节点个数之和 二叉树叶子节点个数 递归方式 (1)如果给定节点pRoot为NULL,则...
  • day__day__up
  • day__day__up
  • 2015-07-07 23:04:34
  • 1196
收藏助手
不良信息举报
您举报文章:二叉树的基本操作
举报原因:
原因补充:

(最多只允许输入30个字)