目录
销毁BTreeDestroy
对于那些非完全二叉树,由于顺序存储结构的空间利用率低,因此二叉树一般都采用链式存储结构,用链表结点来存储二叉树中的每一个结点。在链式二叉树中,结点结构通常包括数据域和若干个指针域。
链式二叉树的结构一般分为两种,一种是二叉链,另一种是三叉链。二叉链的结点包含存储数据的变量,存储左孩子的指针以及存储右孩子的指针。而三叉链的结点除了包含存储数据的变量,存储左孩子的指针以及存储右孩子的指针,还包含存储双亲的指针。特别的在二叉链中,若有n个结点,则一定会有n+1个空指针。
二叉树的遍历是指按某条搜索路径访问树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。因为二叉树是递归定义的,遍历一棵二叉树便要决定对根结点,左子树和右子树的访问顺序。根据访问根结点的顺序不同可以分为前序遍历,中序遍历和后序遍历。以下面这颗二叉树为例:
- BinaryTreeNode* BuyBinaryTreeNode(BTDataType x) // 创建二叉链结点
- {
- BinaryTreeNode* node = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
- if (node == NULL) // 检查结点是否开辟成功
- {
- perror("malloc fail");
- return NULL;
- }
-
- node->data = x; // 先将左右指针置空
- node->left = NULL;
- node->right = NULL;
-
- return node;
- }
-
- int main()
- {
-
- BinaryTreeNode* node1 = BuyBinaryTreeNode(1);
- BinaryTreeNode* node2 = BuyBinaryTreeNode(2);
- BinaryTreeNode* node3 = BuyBinaryTreeNode(3);
- BinaryTreeNode* node4 = BuyBinaryTreeNode(4);
- BinaryTreeNode* node5 = BuyBinaryTreeNode(5);
- BinaryTreeNode* node6 = BuyBinaryTreeNode(6);
- BinaryTreeNode* node7 = BuyBinaryTreeNode(7);
- node1->left = node2;
- node1->right = node3;
- node2->left = node4;
- node2->right = node5;
- node5->left = node6;
- node3->right = node7;
-
- BinaryTreeNode* root = node1;
-
- }
先访问根结点,再访问左子树,最后访问右子树。
先访问左子树,再访问根结点,最后访问右子树。
先访问左子树,再访问右子树,最后访问根结点。
进行层序遍历,需要借助队列。先将根结点入队,然后出队,若不为空,则将它的左右结点入队,然后继续入队出队直到队列为空。
- // 队列
- #include "BinaryTree.h"
-
- typedef struct BinaryTreeNode* QueueDataType; // 存储的数据类型
-
- typedef struct QueueNode
- {
- struct QueueNode* next; // 指向下一个结点
- QueueDataType data; // 存储数据
- }QueueNode;
-
- typedef struct Queue
- {
- QueueNode* head; // 头指针
- QueueNode* tail; // 尾指针
- }Queue;
-
- extern void QueueInit(Queue* pq);
- extern void QueueDestroy(Queue* pq);
- extern void QueuePush(Queue* pq, QueueDataType x);
- extern void QueuePop(Queue* pq);
- extern QueueDataType QueueFront(Queue* pq);
- extern QueueDataType QueueBack(Queue* pq);
- extern size_t QueueSize(Queue* pq);
- extern bool QueueEmpty(Queue* pq);
利用层序遍历可以判断链式二叉树是否为完全二叉树,其思路为:在层序遍历的过程中,如果遇到结点为空则跳出循环,将剩下没有出队的结点依次出队,如果有非空结点出队,则说明该链式二叉树为非完全二叉树;如果剩下没有出队的结点都为空则说明为完全二叉树。
- bool BTreeComplete(BinaryTreeNode* root) // 判断是否为完全二叉树
- {
- Queue q;
- QueueInit(&q);
-
- QueuePush(&q, root);
-
- while (!QueueEmpty(&q))
- {
- QueueDataType front = QueueFront(&q);
- QueuePop(&q);
- if (front)
- {
- /*printf("%d ", front->data);*/
- QueuePush(&q, front->left);
- QueuePush(&q, front->right);
- }
- else
- {
- break; // 遇到空结点跳出循环
- }
- }
-
- while (!QueueEmpty(&q))
- {
- if (QueueFront(&q)!=NULL) // 遇到非空结点,返回false,说明为非完全二叉树
- {
- QueueDestroy(&q);
-
- return false;
- }
- QueuePop(&q);
- }
-
- QueueDestroy(&q);
- return true; // 后面没有非空结点,说明是完全二叉树,返回true
- }






- #include
-
- typedef struct TreeNode
- {
- struct TreeNode* left;
- struct TreeNode* right;
- char ch;
- }TreeNode;
-
- TreeNode* TreeCreate(char* p,int* pi)
- {
- if(p[*pi]!='\0')
- {
- if(p[*pi]!='#')
- {
- TreeNode* node=(TreeNode*)malloc(sizeof(TreeNode));
- if(node==NULL)
- {
- perror("malloc");
- return NULL;
- }
- node->ch=p[*pi];
- (*pi)++;
- node->left=TreeCreate(p,pi);
- node->right=TreeCreate(p,pi);
- return node;
- }
- else
- {
- (*pi)++;
- return NULL;
- }
-
- }
- return NULL;
- }
-
- void TreeInOrder(TreeNode* root)
- {
- if(root==NULL)
- return;
- TreeInOrder(root->left);
- printf("%c ",root->ch);
- TreeInOrder(root->right);
-
- }
-
- int main()
- {
- char str[101];
-
- scanf("%s",str);
-
- int i=0;
-
- TreeInOrder(TreeCreate(str, &i));
-
- return 0;
- }
链式二叉树的销毁应该采用后序遍历的思想,也就是先销毁左子树,再销毁右子树,最后销毁根节点。避免先销毁根节点,左右子树找不到了。
- // 头文件
- typedef int BTDataType;
-
- typedef struct BinaryTreeNode
- {
- struct BinaryTreeNode* left;
- struct BinaryTreeNode* right;
- BTDataType data;
- }BinaryTreeNode;
-
-
-
- extern BinaryTreeNode* BuyBinaryTreeNode(BTDataType x);
- extern void PrevOrder(BinaryTreeNode* root);
- extern void InOrder(BinaryTreeNode* root);
- extern void PostOrder(BinaryTreeNode* root);
- extern int BTreeSize(BinaryTreeNode* root);
- extern int BTreeLeafSize(BinaryTreeNode* root);
- extern int BTreeKLevelSize(BinaryTreeNode* root, int k);
- extern int BTreeDepth(BinaryTreeNode* root);
- extern BinaryTreeNode* BTreeFind(BinaryTreeNode* root, BTDataType x);
- extern void LevelOrder(BinaryTreeNode* root);
- extern bool BTreeComplete(BinaryTreeNode* root);
- extern void BTreeDestroy(BinaryTreeNode* root);
-
- // 源文件
- void PrevOrder(BinaryTreeNode* root) // 前序遍历---根左右
- {
- if (root == NULL)
- {
- printf("N ");
- return;
- }
-
- printf("%d ", root->data);
- PrevOrder(root->left);
- PrevOrder(root->right);
- }
-
- void InOrder(BinaryTreeNode* root) // 中序遍历---左根右
- {
- if (root == NULL)
- {
- printf("N ");
- return;
- }
-
- InOrder(root->left);
- printf("%d ", root->data);
- InOrder(root->right);
- }
-
- void PostOrder(BinaryTreeNode* root) // 后序遍历---左右根
- {
- if (root == NULL)
- {
- printf("N ");
- return;
- }
-
- PostOrder(root->left);
- PostOrder(root->right);
- printf("%d ", root->data);
-
- }
-
- BinaryTreeNode* BuyBinaryTreeNode(BTDataType x) // 创建二叉链结点
- {
- BinaryTreeNode* node = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
- if (node == NULL) // 检查结点是否开辟成功
- {
- perror("malloc fail");
- return NULL;
- }
-
- node->data = x; // 先将左右指针置空
- node->left = NULL;
- node->right = NULL;
-
- return node;
- }
-
- int BTreeSize(BinaryTreeNode* root) // 求链式二叉树的结点个数
- {
- if (root == NULL)
- {
- return 0;
- }
-
- return 1 + BTreeSize(root->left) + BTreeSize(root->right);
- }
-
- int BTreeLeafSize(BinaryTreeNode* root) // 求链式二叉树的叶子结点个数
- {
- if (root == NULL)
- {
- return 0;
- }
-
- if (root->left == NULL && root->right == NULL)
- {
- return 1;
- }
-
- return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);
- }
-
- int BTreeKLevelSize(BinaryTreeNode* root, int k) // 求链式二叉树某一层结点的个数 k+3
- {
- if (root == NULL)
- {
- return 0;
- }
- if (k == 1)
- {
- return 1;
- }
-
- return BTreeKLevelSize(root->left, k - 1) + BTreeKLevelSize(root->right, k - 1);
- }
-
- int BTreeDepth(BinaryTreeNode* root) // 求链式二叉树的层数
- {
- if (!root)
- {
- return 0;
- }
-
- int leftDepth = BTreeDepth(root->left)+1;
- int rightDepth = BTreeDepth(root->right)+1;
-
- return leftDepth > rightDepth ? leftDepth : rightDepth;
- }
-
- BinaryTreeNode* BTreeFind(BinaryTreeNode* root, BTDataType x) // 按值查找
- {
- if (!root)
- {
- return NULL;
- }
- if (root->data == x)
- {
- return root;
- }
- BinaryTreeNode* left = BTreeFind(root->left, x);
-
- if (left)
- return left;
- BinaryTreeNode* right = BTreeFind(root->right, x);
-
- if (right)
- return right;
-
- return NULL;
- }
-
- void LevelOrder(BinaryTreeNode* root) // 层序遍历
- {
- Queue q;
- QueueInit(&q);
-
- QueuePush(&q, root); // 先将根结点入队
-
- while (!QueueEmpty(&q))
- {
- QueueDataType front = QueueFront(&q); // 获取队头元素
- QueuePop(&q); // 出队
- if (front) // 不为空则将左右结点入队
- {
- printf("%d ", front->data);
- QueuePush(&q, front->left);
- QueuePush(&q, front->right);
- }
- }
-
- QueueDestroy(&q);
- }
-
- bool BTreeComplete(BinaryTreeNode* root) // 判断是否为完全二叉树
- {
- Queue q;
- QueueInit(&q);
-
- QueuePush(&q, root);
-
- while (!QueueEmpty(&q))
- {
- QueueDataType front = QueueFront(&q);
- QueuePop(&q);
- if (front)
- {
- /*printf("%d ", front->data);*/
- QueuePush(&q, front->left);
- QueuePush(&q, front->right);
- }
- else
- {
- break; // 遇到空结点跳出循环
- }
- }
-
- while (!QueueEmpty(&q))
- {
- if (QueueFront(&q)!=NULL) // 遇到非空结点,返回false,说明为非完全二叉树
- {
- QueueDestroy(&q);
-
- return false;
- }
- QueuePop(&q);
- }
-
- QueueDestroy(&q);
- return true; // 后面没有非空结点,说明是完全二叉树,返回true
- }
-
- void BTreeDestroy(BinaryTreeNode* root) // 链式二叉树的销毁
- {
- if (!root)
- {
- return;
- }
- BTreeDestroy(root->left);
- BTreeDestroy(root->right);
- free(root);
- }
-
- bool isSameTree(BinaryTreeNode* p, BinaryTreeNode* q) // 相同返回true否则返回false
- {
- if (p == NULL && q == NULL)
- return true;
-
- if (p == NULL || q == NULL)
- return false;
-
- if (p->data != q->data)
- return false;
-
- return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
- }