C语言之二叉树(一)

一、树的定义

树是由n(n >= 0)个节点组成的有限集合。如果n = 0,则称之为空树。

如下图所示

1.A为根节点,它只有直接后驱,但是没有直接前驱。

2.除根以外的其他节点划分为m(m >= 0)个互不相交的有限集合T0,T1..........,TN,每个集合又是一棵树,并称之为根的子树。每棵子树的节点仅有一个直接前驱,但可以有0个或者多个直接后继。途中B和C就是A的子树,他们的直接前驱都只有一个,但是后继则不确定。

下面介绍一些树的基础概念:

1.节点:表示树中的元素,概括数据元素的内容及其指向其子树的分支。上图中所有蓝色圆点都是节点。

2.节点的度:节点的分支数。例如A的度为2,H的度为0。

3.终端节点:分支数为0的节点。上图最下层节点都为终端节点。

4.非终端节点:分支数不为0的节点。

5.节点的层次:树中根节点的层次为1,根节点子树为第2层,依此类推。上图A的层次为1,B的层次为2,D的层次为3,

H的层次为5。

6.树的度:树中所有节点度的最大值。

7.树的深度:树中所有节点层次的最大值。需要注意的是,树的深度是从上往下数,树的高度是从下往上数。

8.有序树、无序树:如果树中每棵子树从左向右的排列拥有一定的顺序不得互换,则称之为有序树,否则称之为无序树。

9.森林:是m(m >= 0)棵互不相交的树的集合。

在树的结构中,节点之间的关系还可以用家族关系来描述:

1.孩子、双亲:某个节点的子树称之为这个节点的孩子,而这个节点又被称之为孩子的双亲。

2.子孙:以某节点为根的子树中所有节点都被称为该节点的子孙。

3.祖先:从根节点到该节点路径上的节点都称之为该节点的祖先。

4.兄弟:同一个双亲的孩子相互为兄弟。

5.堂兄弟:双亲在同一层的节点互为堂兄弟。

 

二、二叉树的定义

二叉树是一种有序树,它是节点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵分别称之为左子树和右子树的互不相交的二叉树组成。他的特点是每个节点至多有两棵子树(即二叉树里面不存在度大于2的节点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。二叉树有以下5种形态:

在实际使用过程中,有两种常见的特殊形态的二叉树。

1.满二叉树

一棵深度为K且有2^{_{k}}-1个节点的二叉树称之为满二叉树。

2.完全二叉树

若设二叉树的高度为h,则共有h层。除第h层外,其他各层的节点数都达到最大个数,第h层从右向左连续若干节点,这就是完全二叉树。

                                完全二叉树                                                              非完全二叉树

 

三、代码构建二叉树

下面代码创建一个顺序二叉树。二叉树每个节点都是一个char型的数据,并且这个二叉树遵循以下规则:

1.所有右孩子的数值大于根节点。

2.所有左孩子的数值小于根节点。

为了程序简易处理,先设定一个数据集合及构建顺序(数据的构建顺序自左向右):e、f、g、h、a、c、b、d。

对应二叉树如下图所示:

 下例代码并没有对二叉树进行遍历,遍历部分内容下个章节进行介绍。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


typedef struct LINK_T                                //二叉树节点结构体
{
  int data;
  struct LINK_T *lchild;
  struct LINK_T *rchild;
}_LINK_T;


_LINK_T *Create_Node(int data);                      //创建二叉树结构点         
_LINK_T *Construct(_LINK_T *head, _LINK_T *node);    //构造二叉树
_LINK_T *Traverse_P(_LINK_T *head);                  //遍历二叉树
int main(int argc, const char *argv[])
{
  int i = 0;
  int data[8] = {'e', 'f', 'h', 'g', 'a', 'c', 'b', 'd'};
  _LINK_T *head;
  head = (_LINK_T*)malloc(sizeof(_LINK_T));
  memset(head, 0, sizeof(head));
  head->data = 0;
  head->lchild = NULL;
  head->rchild = NULL;

  for (i = 0; i < 8; i++)
  {
    Construct(head, Create_Node(data[i]));		
  
  }

  return 0;
}

_LINK_T *Create_Node(int data)
{
  _LINK_T *node;
  node = (_LINK_T*)malloc(sizeof(_LINK_T)); 
  memset(node, 0, sizeof(node));
  node->data = data;
  node->lchild = NULL;
  node->rchild = NULL;

  return node;
}

_LINK_T *Construct(_LINK_T *head, _LINK_T *node)
{
  int i = 0;
  _LINK_T *temp = head;

  while(1)
  {
 
    if (temp->data == 0)                   //第一次插入根节点
    {
      temp->data = node->data;
      break;
    }
    else if (node->data < temp->data)      //如果插入数值小于节点数值,则插入到节点左侧
    {
      if (!temp->lchild)                   //如果左孩子为空,则数据保存到左孩子上         
      {
        temp->lchild = node;
        break;
      }
      else                                 //左孩不为空,则将指针移向左孩
      {
        temp = temp->lchild;
        continue;
      }
    }
    else if (node->data > temp->data)     //如果插入数值大于节点数值,则插入到节点右侧
    {
      if (!temp->rchild)                  //如果右孩子为空,则数据保存到右孩子上         
      {
        temp->rchild = node;
        break;
      }
      else                                //右孩不为空,则将指针移向右孩
      {
        temp = temp->rchild;
        continue;
      }
    }
  
  }

  return;
}

 

仓促成文,不当之处,尚祈方家和读者批评指正。联系邮箱1772348223@qq.com

 

 

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一个简单的 C 语言实现二叉树的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树节点结构 struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; }; // 创建一个新的二叉树节点 struct TreeNode* createNode(int data) { struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode)); if (newNode == NULL) { printf("内存分配失败!\n"); exit(1); } newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } // 向二叉树插入一个节点 struct TreeNode* insertNode(struct TreeNode* root, int data) { if (root == NULL) { return createNode(data); } if (data < root->data) { root->left = insertNode(root->left, data); } else if (data > root->data) { root->right = insertNode(root->right, data); } return root; } // 在二叉树中搜索一个节点 struct TreeNode* searchNode(struct TreeNode* root, int data) { if (root == NULL || root->data == data) { return root; } if (data < root->data) { return searchNode(root->left, data); } else { return searchNode(root->right, data); } } // 删除二叉树中的一个节点 struct TreeNode* deleteNode(struct TreeNode* root, int data) { if (root == NULL) { return root; } if (data < root->data) { root->left = deleteNode(root->left, data); } else if (data > root->data) { root->right = deleteNode(root->right, data); } else { if (root->left == NULL) { struct TreeNode* temp = root->right; free(root); return temp; } else if (root->right == NULL) { struct TreeNode* temp = root->left; free(root); return temp; } struct TreeNode* temp = minValueNode(root->right); root->data = temp->data; root->right = deleteNode(root->right, temp->data); } return root; } // 找到二叉树中的最小值节点 struct TreeNode* minValueNode(struct TreeNode* node) { struct TreeNode* current = node; while (current && current->left != NULL) { current = current->left; } return current; } // 遍历并打印二叉树(中序遍历) void inorderTraversal(struct TreeNode* root) { if (root != NULL) { inorderTraversal(root->left); printf("%d ", root->data); inorderTraversal(root->right); } } int main() { struct TreeNode* root = NULL; // 插入节点 root = insertNode(root, 50); root = insertNode(root, 30); root = insertNode(root, 20); root = insertNode(root, 40); root = insertNode(root, 70); root = insertNode(root, 60); root = insertNode(root, 80); // 中序遍历并打印二叉树 printf("中序遍历结果:"); inorderTraversal(root); printf("\n"); // 搜索节点 int searchData = 40; struct TreeNode* searchResult = searchNode(root, searchData); if (searchResult != NULL) { printf("节点 %d 存在于二叉树中。\n", searchData); } else { printf("节点 %d 不存在于二叉树中。\n", searchData); } // 删除节点 int deleteData = 30; root = deleteNode(root, deleteData); printf("删除节点 %d 后的中序遍历结果:", deleteData); inorderTraversal(root); printf("\n"); return 0; } ``` 这个示例代码实现了二叉树的创建、插入、搜索和删除功能,并对二叉树进行了中序遍历以打印节点。你可以根据需要进行修改和扩展。希望对你有帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值