二叉树基础操作
本篇博客涉及二叉树的概念,分类以及基本操作等部分。
二叉树的概念
一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节
点加上两棵分别称为左子树和右子树的二叉树组成
二叉树的特点:
每个结点最多有两棵子树,即二叉树不存在度大于2的结点二叉树的子树有左右之分,其子树的次序不能颠
满二叉树&完全二叉树
满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树, 并且所有叶子节点都在同一层上
完全二叉树:如果一棵具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同,称为完全二叉树
二叉树的实现(C)
二叉树结构体
#include<windows.h> #include<stdio.h> #include"stack.h" #include"queue.h" typedef int BTDataType; typedef struct BTreeNode { struct BTreeNode* left; struct BTreeNode* right; BTDataType _data; }BTNode;
创建节点
BTNode* BuyBTNode(BTDataType x) { BTNode* _new; _new = (BTNode*)malloc(sizeof(BTNode)); _new->left = NULL; _new->right = NULL; _new->_data = x; return _new; }创建二叉树
BTNode* CreateBTree(BTDataType* a, size_t* pIndex, BTDataType invalid)//给一个pindex用于迭代 { // int a[] = { 1, 2, 3, '#', '#',4,'#', '#', 5, 6,'#' ,'#' ,'#' }; BTNode* tree; BTDataType* b;//b为了将a存起来下一次好用 b = a; a = a + *pIndex; if (*a == invalid) { (*pIndex)++; return NULL; } tree = BuyBTNode(*a); (*pIndex)++; a = b; tree->left = CreateBTree(a, pIndex, invalid); tree->right = CreateBTree(a, pIndex, invalid); return tree; }
前中后序遍历
由于便于观察,代码中给出打印函数。
前序为先遍历节点,在走左子树,在走右子树。
中序为先走左子树,在走节点,在走右子树。
后序为先走左子树在走右子树,在走节点。
void BTreePrevOrder(BTNode* root)//前序 { if (root == NULL) { return; } printf("%d ",root->_data); BTreePrevOrder(root->left); BTreePrevOrder(root->right); } void BTreeInOrder(BTNode* root)//中序 { if (root == NULL) { return; } BTreeInOrder(root->left); printf("%d ", root->_data); BTreeInOrder(root->right); } void BTreePostOrder(BTNode* root)//后续 { if (root == NULL) { return; } BTreePostOrder(root->left); BTreePostOrder(root->right); printf("%d ", root->_data); }
节点数
遍历节点并且打印出节点数
size_t BTreeSize(BTNode* root) { if (root == NULL) { return 0; } return BTreeSize(root->left) + BTreeSize(root->right)+1; }
叶子节点
依旧是利用递归,当发现一片叶子时递归+1。
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); }
第K层的节点数量
当递归到K层时返回1.
size_t BTreeKLevelSize(BTNode* root, size_t k) { if (root == NULL) { return 0; } if (k == 1) { return 1; } k--; return BTreeKLevelSize(root->left,k) + BTreeKLevelSize(root->left,k); }
二叉树查找
BTNode* BTreeFind(BTNode* root, BTDataType x) { if (root == NULL) { return NULL; } if (root->_data == x) { return root; } BTreeFind(root->left, x); BTreeFind(root->right,x); return NULL; }
判断完全二叉树
int IsCompleteBTree(BTNode* root) { Queue* q = (Queue*)malloc(sizeof(Queue)); QueueInit(q); QueuePush(q, root); while (q->_head->_next->_data!=NULL) { QueuePush(q, q->_head->_next->_data->left); QueuePush(q, q->_head->_next->_data->right); QueuePop(q); } while (QueueEmpty(q) != 0) { if (q->_head->_next->_data == NULL) { QueuePop(q); } else { return 0; } } return 1; }判断完全二叉树(flag法)
int IsCompleteBTree1(BTNode* root) { int flag = 0; Queue* q = (Queue*)malloc(sizeof(Queue)); QueueInit(q); QueuePush(q, root); while (QueueEmpty(q)!=0) { QueuePush(q, q->_head->_next->_data->left); QueuePush(q, q->_head->_next->_data->right); QueuePop(q); if (q->_head->_next->_data == NULL) { flag = 1; } if (flag = 1 && q->_head->_next->_data != NULL) { return 0; } } return 1; }前序非递归
void BTreePrevOrderNonR(BTNode* root) { Stack s; StackInit(&s); BTNode* ptr = root; while (ptr || StackEmpty(&s) != 0) { while (ptr) { printf("%d ", ptr->_data); StackPush(&s, ptr); ptr = ptr->left; } ptr = s._array[s._top-1]->right; StackPop(&s); } }中序非递归
void BTreeInOrderNonR(BTNode* root) { Stack s; StackInit(&s); BTNode* ptr = root; while (ptr || StackEmpty(&s) != 0) { while (ptr) { StackPush(&s,ptr); ptr = ptr->left; } printf("%d ",s._array[s._top-1]->_data); ptr = s._array[s._top - 1]->right; StackPop(&s); } }后序非递归
void BTreeInOrderNonR(BTNode* root) { Stack s; StackInit(&s); BTNode* ptr = root; while (ptr || StackEmpty(&s) != 0) { while (ptr) { StackPush(&s,ptr); ptr = ptr->left; } printf("%d ",s._array[s._top-1]->_data); ptr = s._array[s._top - 1]->right; StackPop(&s); } }