【数据结构】二叉树(下)

简介: 【数据结构】二叉树(下)

二叉树的链式结构

  链式二叉树的增删查改是没有意义的,建立在二叉树基础上的搜索二叉树才具备增删查改的意义。但是链式二叉树是基础,就像修房子得先打地基一样。

二叉树的遍历

首先确定一个概念,二叉树分为空树和非空树,只要是非空树就有根节点、根节点的左子树和根节点的右子树。二叉树的定义是递归式的。

 二叉树遍历是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作依次。访问节点所做的操作依赖于具体的应用问题,遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

 二叉树一共有四种遍历方式,前序遍历(先根遍历)、中序遍历(中根遍历)、后序遍历(后根遍历)和层序遍历。

前序遍历(先根遍历)

  访问根节点的操作发生在遍历其左右子树之前。在遍历时,会不断向下遍历知道遇到空树才停止。

e1f4f9d7bb084fe0ad9c1831613818ea.png

void PrevOrder(BTNode* root)
{
  if (NULL == root)
  {
    printf("NULL ");
    return;
  }
  printf("%d ", root->data);
  PrevOrder(root->left);
  PrevOrder(root->right);
}

 栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->深蓝色->粉色->金色->紫色->青色。

fac4d8cc7ab74c8d83533721b8c265b2.png

中序遍历(中根遍历)

  访问根节点的操作放生在遍历其左右子树之间。


54d3e49e32f24fc7bd84da91c8007999.png

void InOrder(BTNode* root)
{
  if (NULL == root)
  {
    printf("NULL ");
    return;
  }
  InOrder(root->left);
  printf("%d ", root->data);
  InOrder(root->right);
}

 栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色->青色->紫色。

21f06f17eab043c1a343477ab376358f.png

后序遍历(后根遍历)

  访问根节点的操作发生在遍历其左右子树之后。


0119b0dcafce4d18b03596d1ea8e3531.png

void PostOrder(BTNode* root)
{
  if (NULL == root)
  {
    printf("NULL ");
    return;
  }
  PostOrder(root->left);
  PostOrder(root->right);
  printf("%d ", root->data);
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色->青色->紫色。

191cd7c525864c9e8679877f528d9557.png

层序遍历

  从第一层开始,每层从左到右,一层一层的走。四种遍历中,只有层序遍历是非递归的,它采用的是队列来实现的。


47942d6a2ab240d4a502825e8182c565.png

void LevelOrder(BTNode* root)
{
  Queue q;
  QueueInit(&q);
  // 先将根节点存入队列
  if (root)
    QueuePush(&q, root);
  // 判空,如果为空就不执行以下语句
  while (!QueueEmpty(&q))
  {
    // 获取队头,打印之后,移出队列
    BTNode* front = QueueFront(&q);
    printf("%d ", front->data);
    QueuePop(&q);
    if (front->left)
      QueuePush(&q, front->left);
    if (front->right)
      QueuePush(&q, front->right);
  }
  printf("\n");
  QueueDestroy(&q);
}

83f48b87f2764dd09e0640666011e996.png

二叉树的构建

  二叉树的构建根据三种递归的遍历方式进行构建,可以进行前序、中序、后序构建,我这里使用的是前序构建。

BTNode* CreatBinaryTree(BTDataType* a, int* pi)
{
  if (-1 == a[*pi])
  {
    (*pi)++;
    return NULL;
  }
  BTNode* root = (BTNode*)malloc(sizeof(BTNode));
  if (NULL == root)
  {
    perror("malloc fail");
    exit(-1);
  }
  root->data = a[(*pi)++];
  root->left = CreatBinaryTree(a, pi);
  root->right = CreatBinaryTree(a, pi);
  return root;
}

二叉树的节点数

int TreeSize(BTNode* root)
{
  if (NULL == root)
  {
    return 0;
  }
  return TreeSize(root->left) + TreeSize(root->right) + 1;
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色->青色->紫色,最后返回的值是6。


913941f2678f4c268518b6f655bd5491.png

二叉树的叶子数

int TreeLeafSize(BTNode* root)
{
  if (NULL == root)
  {
    return 0;
  }
  if (NULL == root->left && NULL == root->right)
  {
    return 1;
  }
  return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}


栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为3。


21c8b0f8e63c4445a55c3419bde33210.png

二叉树的高度

int TreeHeight(BTNode* root)
{
  if (NULL == root)
  {
    return 0;
  }
  int left = TreeHeight(root->left);
  int right = TreeHeight(root->right);
  return  (left > right ? left : right) + 1;
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为3。

32112009a06e460bb5c7b156f490e555.png


二叉树K层节点数

int TreeKLevelSize(BTNode* root, int k)
{
  if (NULL == root)
  {
    return 0;
  }
  if (1 == k)
  {
    return 1;
  }
  return TreeKLevelSize(root->left, k - 1) + TreeKLevelSize(root->right, k - 1);
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为3。


3ee00ac59d1f4ce388891799aea8824c.png

查找值为X的节点

BTNode* TreeFind(BTNode* root, BTDataType x)
{
  if (NULL == root)
    return NULL;
  if (x == root->data)
    return root;
  BTNode* ret1 = TreeFind(root->left, x);
  if (ret1)
    return ret1;
  BTNode* ret2 = TreeFind(root->right, x);
  if (ret2)
    return ret2;
  return NULL;
}

栈帧空间的创建销毁顺序按照下图进行的,向右的箭头表示创建,向左的箭头表示销毁。创建销毁的顺序是橙色->绿色->蓝色->粉色->深蓝色->金色,最后结果为数字5节点的地址

d3c96c360e2f44a79e40fa41312bc161.png

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

bool TreeComplete(BTNode* root)
{
  Queue q;
  QueueInit(&q);
  if (root)
    QueuePush(&q, root);
  // 若队列为空,则不执行
  while (!QueueEmpty(&q))
  {
    BTNode* front = QueueFront(&q);
    QueuePop(&q);
    // 判断front是否为空,为空则跳出循环
    if (!front)
    {
      break;
    }
    else
    {
      QueuePush(&q, front->left);
      QueuePush(&q, front->right);
    }
  }
  // 若队列为空,则不执行
  while (!QueueEmpty(&q))
  {
    BTNode* front = QueueFront(&q);
    QueuePop(&q);
    if (front)
    {
      QueueDestroy(&q);
      return false;
    }
  }
  QueueDestroy(&q);
  return true;
}

二叉树的销毁

// 二叉树销毁
void TreeDestory(BTNode* root)
{
  if (NULL == root)
  {
    return;
  }
  TreeDestory(root->left);
  TreeDestory(root->right);
  free(root);
}
目录
相关文章
|
20天前
|
存储 算法
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
14 0
|
20天前
|
存储 算法 Linux
【数据结构和算法】---二叉树(1)--树概念及结构
【数据结构和算法】---二叉树(1)--树概念及结构
14 0
|
20天前
【数据结构】判断二叉树是否是完全二叉树
【数据结构】判断二叉树是否是完全二叉树
16 5
|
20天前
【数据结构】链式二叉树的层序遍历
【数据结构】链式二叉树的层序遍历
19 5
|
20天前
|
存储 测试技术
【数据结构】手把手分析:链式二叉树的实现
【数据结构】手把手分析:链式二叉树的实现
20 5
|
20天前
|
算法 分布式数据库
【数据结构和算法】--- 二叉树(5)--二叉树OJ题
【数据结构和算法】--- 二叉树(5)--二叉树OJ题
12 1
|
21天前
|
算法 API 数据处理
数据结构——二叉树的实现
数据结构——二叉树的实现
17 1
|
21天前
|
算法
【C/数据结构与算法】:二叉树经典OJ
【C/数据结构与算法】:二叉树经典OJ
15 0
【C/数据结构与算法】:二叉树经典OJ
|
28天前
|
存储 算法
【树】数据结构——树和二叉树的概念&笔记
【树】数据结构——树和二叉树的概念&笔记
|
1月前
|
存储
数据结构——二叉树
数据结构——二叉树
15 1