C语言实现数据结构代码(三)-树与二叉树-二叉树-二叉树的定义

目录

1.1二叉树的定义

 1.2二叉树的主要性质

1.3二叉树的存储结构

1.3.1 顺序存储结构

1.3.2 链式存储结构

 


1.1二叉树的定义

给一般的二叉树加上两个限制条件就可以得到二叉树:

(1)每个结点最多只有两颗子树,即二叉树中结点的度只能为0,1,2。

(2)子树有左右顺序之分,不能颠倒。

 

满二叉树在一棵二叉树中,所有的分支结点都有左孩子结点和右孩子结点,并且叶子结点都集中在二叉树的最下一层。例如,图6-4a就是一颗满二叉树。
完全二叉树

① 对一棵深度为k的满二叉树编号。(从上到下,从左至右,从1开始。)

② 对一棵深度为k、有n个结点的二叉树编号。

③ 若②中各结点的编号与①中相同位置上结点的编号都相同。

     那么,②中的树为完全二叉树。

一棵完全二叉树是由一棵满二叉树,从右至左,从下往上,逐个删除结点所得到的。如果跳着删,则得到的不是完全二叉树。


 1.2二叉树的主要性质

性质1非空二叉树上叶子结点数等于双分支结点数+1

 证明: 1、设二叉树中叶子结点的个数为 N0,单分支结点的个数为N1,双分支结点的个数为N2。

                  那么,总结点的个数= N0+N1+N2

             2、 在二叉树中,所有结点的分支数=1*单分支结点的个数 + 2*双分支结点的个数。

                 即  总分支数=N1+2N2

             3、 在二叉树中,除了根节点,每个结点都有一个分支指向它。 即  总分支数=总结点数-1=N0+N1+N2-1

                (该条结论适用于所有的树)

             所以,总分支数=N1+2N2=N0+N1+N2-1

             得出, N0=N2+1

性质二:二叉树的第 i 层上最多有 2^{i-1} (i\geq 1{\color{Blue} {\color{Green} }})个结点。 

结点最多的情况就是满二叉树的情况,此时,二叉树上每一层的结点数就构成了一个

首项为1、公比为2 的等比数列,通项为 2^{i-1},i为层数。

性质三:高度(深度)为k的二叉树,最多有 2^{k}-1 (k\geq 1)  个结点。也就是,满二叉树前 k 层的结点个数为 2^{k}-1

由刚刚性质二中的,等比数列求和可以算出,前k项和为 \frac{1*(1-2^{n})}{1-2}

性质四:完全二叉树中,某结点的双亲结点、左孩子结点、右孩子结点。

有 n 个结点的完全二叉树,对各结点从上往下,从左至右,依次编号,编号范围为 1~n。设 i 为某结点 a 的编号,则:

①  i\neq 0 ,则 a 双亲结点的编号为  \frac{i}{2} 。

②  2i\leq n ,则 a 的左孩子结点编号为 2i 。

      2i> n ,则 a 无左孩子结点。

③ 2i+1\leq n ,则 a 的右孩子编号为 2i+1 。

    2i+1> n ,则 a 无右孩子结点。

性质五:函数Catalan():给定 n 个结点,能构成 h(n) 种不同的二叉树,h(n)=\frac{C_{2n}^{n}}{n+1} 。

性质六:具有 n (n>=1) 个结点的完全二叉树的高度(深度)为 


1.3二叉树的存储结构

1.3.1 顺序存储结构

用一个数组来存储一棵二叉树,这种存储方式最适合于完全二叉树,存储一般的二叉树会浪费大量的存储空间。

将完全二叉树中的结点值按照编号依次存入一个一维数组中,就完成了一棵二叉树的顺序存储。

例如,知道了结点A的下标为1,要得到A的左孩子结点只需要访问BTree[2*i]即可。

类似的,当知道一个结点的下标为 i 时,若2i <=n ,那么 i 的左孩子结点就存在BTree[2*i]中。

1.3.2 链式存储结构

data表示数据域,用来存储对应的数据元素;lchild和rchild分别表示左指针域和右指针域,

分别用于存储左孩子结点和右孩子结点的位置。

这种结构又称为二叉链表存储结构

对应的结点类型定义为:

typedef struct BTNode
{
    char data;
    struct BTNode *lchild;
    struct BTNode *rchild;
}BTNode;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
平衡二叉树是一种特殊的二叉树,它的左右子的高度差不超过1。AVL是一种自平衡的二叉搜索,它的高度始终保持在O(log n)。 下面是C语言实现平衡二叉树(AVL)的代码: ``` #include <stdio.h> #include <stdlib.h> /* 定义平衡二叉树节点结构体 */ struct AVLNode { int data; // 存储的数据 int height; // 节点高度 struct AVLNode *leftChild; // 左子 struct AVLNode *rightChild; // 右子 }; /* 获取节点高度 */ int getHeight(struct AVLNode *node) { if (node == NULL) { return -1; } else { return node->height; } } /* 获取节点平衡因子 */ int getBalanceFactor(struct AVLNode *node) { if (node == NULL) { return 0; } else { return getHeight(node->leftChild) - getHeight(node->rightChild); } } /* 更新节点高度 */ void updateHeight(struct AVLNode *node) { node->height = 1 + (getHeight(node->leftChild) > getHeight(node->rightChild) ? getHeight(node->leftChild) : getHeight(node->rightChild)); } /* 右旋操作 */ struct AVLNode *rotateRight(struct AVLNode *node) { struct AVLNode *newRoot = node->leftChild; node->leftChild = newRoot->rightChild; newRoot->rightChild = node; updateHeight(node); updateHeight(newRoot); return newRoot; } /* 左旋操作 */ struct AVLNode *rotateLeft(struct AVLNode *node) { struct AVLNode *newRoot = node->rightChild; node->rightChild = newRoot->leftChild; newRoot->leftChild = node; updateHeight(node); updateHeight(newRoot); return newRoot; } /* 插入操作 */ struct AVLNode *insert(struct AVLNode *root, int data) { if (root == NULL) { root = (struct AVLNode *) malloc(sizeof(struct AVLNode)); root->data = data; root->height = 0; root->leftChild = NULL; root->rightChild = NULL; } else if (data < root->data) { root->leftChild = insert(root->leftChild, data); if (getHeight(root->leftChild) - getHeight(root->rightChild) == 2) { if (data < root->leftChild->data) { root = rotateRight(root); } else { root->leftChild = rotateLeft(root->leftChild); root = rotateRight(root); } } } else if (data > root->data) { root->rightChild = insert(root->rightChild, data); if (getHeight(root->rightChild) - getHeight(root->leftChild) == 2) { if (data > root->rightChild->data) { root = rotateLeft(root); } else { root->rightChild = rotateRight(root->rightChild); root = rotateLeft(root); } } } updateHeight(root); return root; } /* 序遍历 */ void inOrderTraversal(struct AVLNode *root) { if (root != NULL) { inOrderTraversal(root->leftChild); printf("%d ", root->data); inOrderTraversal(root->rightChild); } } int main() { struct AVLNode *root = NULL; int data[] = {5, 2, 8, 1, 3, 6, 9}; int len = sizeof(data) / sizeof(data[0]); int i; for (i = 0; i < len; i++) { root = insert(root, data[i]); } inOrderTraversal(root); return 0; } ``` 以上代码实现了平衡二叉树的插入和序遍历操作。在插入操作据插入节点的值和当前节点的值的大小关系,不断递归向左或向右子进行插入操作,并在递归返回时更新节点高度和进行平衡操作。在平衡操作节点的平衡因子进行旋转操作,使重新平衡。在序遍历操作,按照左子节点、右子的顺序遍历节点,输出节点的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值