前言
对于一般的二叉树(非完全二叉树,满二叉树)而言。用顺序表去存储,会造成空间的浪费。所以一般采用链式结构实现。
对于非完全非满二叉树,增删查改并没有什么实际意义,对于以后学到的搜索二叉树会有。但是一般的操作是 前序、中序、后序 遍历二叉树,也可以写计算二叉树的深度,结点数,叶子结点数的功能函数。
链式结构实现
创建结点结构体
typedef struct BinaryTreeNode
{
struct BinaryTreeNode* right;
struct BinaryTreeNode* left;
int data;
}BTNode;
构建树逻辑结构
BTNode* CreatTree()
{
BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
n1->data = 1;
n2->data = 2;
n3->data = 3;
n4->data = 4;
n5->data = 5;
n6->data = 6;
n1->left = n2;
n1->right = n4;
n2->left = n3;
n2->right = NULL;
n3->left = NULL;
n3->right = NULL;
n4->left = n5;
n4->right = n6;
n5->left = NULL;
n5->right = NULL;
n6->left = NULL;
n6->right = NULL;
return n1;
}
遍历二叉树
前序遍历:先访问根节点,再遍历其左子树、右子树。
中序遍历:先访问左子树,再访问根节点、其右子树。
后续遍历:先访问右子树,再访问根节点、其左子树。
运用递归的思想
前序遍历
void PreTravel(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->data);
PreTravel(root->left);
PreTravel(root->right);
}
中序遍历
void InTravel(BTNode* root)
{
if (root== NULL)
{
printf("NULL ");
return;
}
InTravel(root->left);
printf("%d ", root->data);
InTravel(root->right);
}
后序遍历
void PostTravel(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostTravel(root->left);
PostTravel(root->right);
printf("%d ", root->data);
}
计算二叉树高度、结点数、叶子数
结点数:
int TreeNodeSize(BTNode* root)
{
return root == NULL ? 0 :
TreeNodeSize(root->left) + TreeNodeSize(root->right) + 1;
}
叶子数:
int TreeLeafSize(BTNode* root)
{
if (root == NULL)
return 0;
if (root->left == NULL && root->right == NULL)
return 1;
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
高度:
int TreeHeightSize(BTNode* root)
{
if (root == NULL)
return 0;
int leftsize= TreeHeightSize(root->left);
int rightsize = TreeHeightSize(root->right);
return rightsize > leftsize ? rightsize + 1:leftsize + 1;
}
销毁
void Destory(BTNode* root)
{
if (root == NULL)
return;
Destory(root->left);
Destory(root->right);
free(root);
}
查找值为x的节点
BTNode* TreeFind(BTNode* root, BTTypde x)
{
if (root == NULL)
return NULL;
if (root->data==x)
return root;
BTNode*left= TreeFind(root->left, x);
if (left)
return left;
BTNode*right=TreeFind(root->right, x);
if (left)
return right;
return NULL;
}
层序遍历
利用队列。
先入根,再出队列,同时把左右子孩子入队列,依次如下,直到队列为空。
void BinaryTreeLevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!EmptyQueue(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%d ", front->_data);
if(front->_left)
QueuePush(&q, root->_left);
if(front->_right)
QueuePush(&q, root->_right);
}
QueueDestory(&q);
}
判断是否为完全二叉树
也是利用队列,出队就入左右孩子,一旦出队列的是空,就停止,下面判断,如果后面全是空就是完全二叉树,但凡有一个非空就不是完全二叉树。
int BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
break;
QueuePush(&q, root->_left);
QueuePush(&q, root->_right);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
QueueDestory(&q);
return false;
}
}
QueueDestory(&q);
return true;
}