1.递归
BTNode* BinaryTreeCreate(BTDataType* a, int num, int* i) //前序,VLR ,数组,元素个数,元素下标
{
if (a[*i] != '#'&& (*i)<num)
{
BTNode* root = BuyNodeTree(a[*i]);
(*i)++;
root->_left = BinaryTreeCreate(a, num, i);
(*i)++;
root->_right = BinaryTreeCreate(a, num, i);
return root;
}
else
return NULL;
}
int BinaryTreeNodeSize(BTNode* root)
{
if (root == NULL)
return 0;
return BinaryTreeNodeSize(root->_left) + BinaryTreeNodeSize(root->_right) + 1;
}
//后序销毁树
void BinaryTreeDestory(BTNode* root)
{
if (root==NULL)
{
return;
}
BinaryTreeDestory(root->_left);
BinaryTreeDestory(root->_right);
free(root);
}
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
return 0;
if (root->_left == NULL && root->_right == NULL)
return 1;
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}
int BinaryTreeDepth(BTNode* root) //计算树的深度
{
if (root == NULL)
return 0;
int _left = BinaryTreeDepth(root->_left) + 1;
int _right = BinaryTreeDepth(root->_right) + 1;
return _left > _right ? _left : _right;
}
BTNode* FindBinaryTreeNode(BTNode* root, BTDataType x) //查找结点
{
BTNode* _left;
BTNode* _right;
if (root == NULL || root->_data == x)
return root;
_left = FindBinaryTreeNode(root->_left, x);
if (_left)
return _left;
_right = FindBinaryTreeNode(root->_right, x);
if (_right)
return _right;
return NULL;
}
void BinaryTreePrevOrder(BTNode* root) //前序遍历
{
if (root == NULL)
return;
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left);
BinaryTreePrevOrder(root->_right);
}
void BinaryTreeInOrder(BTNode* root) //中序遍历
{
if (root == NULL)
return;
BinaryTreeInOrder(root->_left);
printf("%c ", root->_data);
BinaryTreeInOrder(root->_right);
}
void BinaryTreePostOrder(BTNode* root) //后序遍历
{
if (root == NULL)
return;
BinaryTreePostOrder(root->_left);
BinaryTreePostOrder(root->_right);
printf("%c ", root->_data);
}
2.非递归
(1)层序遍历
思想:用一个队列,将树顶元素压入,在出元素的时候将其左右孩子压入,这样可以做到先入先出
void BinaryTreeLevelOrder(BTNode* root) //层序遍历
{
Queue q; //创建一个队列
QueueInit(&q);
if (root == NULL)
return;
QueuePush(&q, root);
while (QueueEmpty(&q)) //队列不为空,就还有元素
{
BTNode* front = QueueFront(&q);
if (front->_left) //队列首元素的左指针若不为空,则将左指针的元素压入队列
{
QueuePush(&q, front->_left);
}
if (front->_right) //右指针同理
{
QueuePush(&q, front->_right);
}
printf("%c ", front->_data); //遍历队列首元素
QueuePop(&q); //pop出首元素
}
}
(2)判断是不是完全二叉树(层序遍历)
int BinaryTreeComplete(BTNode* root) //判断是不是完全二叉树
{
int flag = 0; //如果压入第一个空指针后,后边还有元素,则不是完全二叉树
Queue q;
QueueInit(&q); //如果压入第一个空指针后,后边都是空指针,则是完全二叉树
if (root == NULL)
return 1;
QueuePush(&q, root);
while (QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
if (front != NULL)
{
if (flag == 1)
return 0;
QueuePush(&q, front->_left);
QueuePush(&q, front->_right);
}
else
{
flag = 1; //记录队列中压入的第一个空指针
}
QueuePop(&q);
}
return 1;
}
(3)前(中)序遍历(非递归)
思想:建一个栈,记录栈顶元素后,pop掉,再访问其右树,转化为子问题
void BinaryTreePrevOrderNoD(BTNode* root) //前序遍历非递归
{
Stack s;
StackInit(&s);
BTNode* cur = root; //cur总指向一个树的根节点
if (root == NULL)
{
printf("树为空!\n");
return;
}
while (cur || StackEmpty(&s))
{
//先访问树的左树
while (cur)
{
printf("%c ", cur->_data);
StackPush(&s, cur);
cur = cur->_left;
}
//cur为空,先pop掉,再访问top的右树
BTNode* top = StackTop(&s);
StackPop(&s);
//子问题访问右树
cur = top->_right;
}
}
void BinaryTreeInOrderNoD(BTNode* root) //中序遍历非递归
{
Stack s;
StackInit(&s);
BTNode* cur = root; //cur总指向一个树的根节点
if (root == NULL)
{
printf("树为空!\n");
return;
}
while (cur || StackEmpty(&s))
{
//先入树的左节点
while (cur)
{
StackPush(&s, cur);
cur = cur->_left;
}
BTNode* top = StackTop(&s);
printf("%c ", top->_data);
StackPop(&s);
cur = top->_right;
}
}
(4)后序遍历(非递归)
void BinaryTreePostOrderNoD(BTNode* root) //后序遍历非递归
{
BTNode* top;
BTNode* prev=NULL;
Stack s;
StackInit(&s);
BTNode* cur = root; //cur总指向一个树的根节点
if (root == NULL)
{
printf("树为空!\n");
return;
}
while (cur || StackEmpty(&s))
{
while (cur)
{
StackPush(&s, cur);
cur = cur->_left;
}
//这里的cur始终为空
top = StackTop(&s);
if (top->_right == NULL||top->_right == prev) //一旦访问过右节点,就可以遍历根节点了
{
printf("%c ", top->_data);
prev = top;
//标记上一次访问的节点,即访问根节点之前,要访问右树节点
StackPop(&s);
}
else
{
cur = top->_right;
}
}
}
(5)二叉树的镜像,左右子树交换
void BinaryTreeJingXiang(BTNode* root) //二叉树的镜像
{
BTNode* tmp;
if (root == NULL)
return;
tmp = root->_left;
root->_left = root->_right;
root->_right = tmp;
BinaryTreeJingXiang(root->_left);
BinaryTreeJingXiang(root->_right);
}
3.二叉树的key/value模型
#include "BSTree.h"
BSTreeNode* BuyNode(KeyDataType key, ValueDataType value)
{
BSTreeNode* newNode = (BSTreeNode*)malloc(sizeof(BSTreeNode));
newNode->_left = NULL;
newNode->_right = NULL;
newNode->key = (KeyDataType)malloc(strlen(key) + 1);
strcpy(newNode->key, key);
newNode->value = (ValueDataType)malloc(strlen(value) + 1);
strcpy(newNode->value, value);
return newNode;
}
int InsertNodeR(BSTreeNode** tree, KeyDataType key, ValueDataType value)
{
assert(tree);
BSTreeNode* root = *tree;
if (*tree == NULL)
{
*tree = BuyNode(key, value);
return 1;
}
else
{
if (strcmp(root->key, key) > 0)
{
return InsertNodeR(&(root->_left), key, value);
}
else if (strcmp(root->key, key) < 0)
{
return InsertNodeR(&(root->_right), key, value);
}
else
{
printf("已有该元素,插入失败!\n");
return 0;
}
}
}
int RemoveNodeR(BSTreeNode** tree, KeyDataType key)
{
if (*tree == NULL)
return 0;
else
{
BSTreeNode* del = FindNode(*tree, key);
if (del == NULL)
{
printf("删除失败!\n");
return 0;
}
if (del->_left == NULL)
{
del = del->_right; //del就相当于父亲节点指向del的指针
free(del);
del = NULL;
printf("删除成功!\n");
return 1;
}
else if (del->_right == NULL)
{
del = del->_left;
free(del);
del = NULL;
printf("删除成功!\n");
return 1;
}
else
{
BSTreeNode* replace = del->_right;
while (replace->_left)
{
replace = replace->_left;
}
strcpy(del->key, replace->key); //replace为右树的最小值
strcpy(del->value, replace->value);
return RemoveNodeR(&(del->_right), replace->key); //转化为删除右树的替代节点的子问题
}
}
}
BSTreeNode* FindNode(BSTreeNode* tree, KeyDataType key)
{
while (tree)
{
if (strcmp(tree->key, key) > 0)
{
tree = tree->_left;
}
else if (strcmp(tree->key, key) < 0)
{
tree = tree->_right;
}
else
{
printf("找到了!\n%s:%s\n",tree->key,tree->value);
return tree;
}
}
printf("没找到!\n");
return NULL;
}