二叉树链式结构的遍历
所谓遍历即沿着某条搜索路线,依次对树中每个结点均做一次且做一次访问。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,是二叉树上进行其他运算之基础。
前序/中序/后序的递归结构遍历:是根据访问节点操作发生未知明明
- NLR:前序遍历:访问根节点的操作发生在遍历其左右子树之前
- LNR:中序遍历:访问根节点的操作发生在遍历其左右子树之间
- LRN:后序遍历:访问根节点的操作发生在遍历其左右子树之后
typedef char DataType;
typedef struct BNode
{
DataType _data;
struct BNode* _left;
struct BNode* _right;
}BNode;
//ABD##E#H##CF##G##
BNode* creatBtree(DataType arr[], int* idx)
{
if (arr[*idx] == '#')
{
(*idx)++;
return NULL;
}
else
{
//创建以当前数据为根的子树
BNode* root = (BNode*)malloc(sizeof(BNode));
root->_data = arr[*idx];
++(*idx);
root->_left = creatBtree(arr, idx);
root->_right = creatBtree(arr, idx);
return root;
}
}
//前序
void preOrder(BNode* root)
{
//根 左子树 右子树
if (root)
{
printf("%c", root->_data);
preOrder(root->_left);
preOrder(root->_right);
}
}
//中序
void inOrder(BNode* root)
{
//左子树 根 右子树
if (root)
{
inOrder(root->_left);
printf("%c", root->_data);
inOrder(root->_right);
}
}
//后序
void postOrder(BNode* root)
{
//左子树 右子树 根
if (root)
{
postOrder(root->_left);
postOrder(root->_right);
printf("%c", root->_data);
}
}
int bTreeSize1(BNode* root)
{
if (root == NULL)
return 0;
//root左子树的结点 + root右子树的结点 + 1
return bTreeSize1(root->_left) + bTreeSize1(root->_right) + 1;
}
//写法2
void bTreeSize2(BNode* root, int* idx)
{
if (root)
{
++(*idx);
bTreeSize2(root->_left, idx);
bTreeSize2(root->_right, idx);
}
}
int bTreeLeafSize(BNode* root)
{
if (root == NULL)
return 0;
else if (root->_left == NULL && root->_right == NULL)
return 1;
//左右子树的叶子
return bTreeLeafSize(root->_left) + bTreeLeafSize(root->_right);
}
int bTreeKSize(BNode* root, int k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
//左右子树第K - 1层结点和
return bTreeKSize(root->_left, k - 1) + bTreeKSize(root->_right, k - 1);
}
BNode* bTreeFind(BNode* root, DataType ch)
{
BNode* node;
if (root == NULL)
return NULL;
if (root->_data == ch)
return root;
//左子树
node = bTreeFind(root->_left, ch);
if (node)
return node;
//右子树
return bTreeFind(root->_right, ch);
}
//层序遍历(借助之前的队列代码接口)
//void bTreeLevelOrder(BNode* root)
//{
// //借助队列保存节点
// Queue q;
// initQueue(&q);
// //根节点存入队列
// if (root)
// queuePush(&q, root);
// //遍历队列中的每一个节点
// while (!queueEmpty(&q))
// {
// //获取队头元素
// Node* front = queueFront(&q);
// //出队
// queuePop(&q);
//
// printf("%d", front->_data);
// //保存队头元素的左右孩子节点
// if (front->_left)
// queuePush(&q, front->_left);
// if (front->_right)
// queuePush(&q, front->_right);
// }
// printf("\n");
//}
void bTreeDestroy(BNode** root)
{
bTreeDestroy(&((*root)->_left));
bTreeDestroy(&((*root)->_right));
free(*root);
*root = NULL;
}
//完全二叉树:层序遍历,节点连续,中间没有空节点
//int isCompleteBtree(Node* root)
//{
// Queue q;
// initQueue(&q);
// if (root)
// queuePush(&q, root);
// //遍历队列中的每一个节点
// while (!queueEmpty(&q))
// {
// //获取队头元素
// Node* front = queueFront(&q);
// //出队
// queuePop(&q);
// if (front)
// {
// queuePush(&q, front->_left);
// queuePush(&q, front->_right);
// }
// else
// break;
// }
// //查看剩余元素中,是否有非空节点
// while (!queueEmpty(&q))
// {
// Node* front = queueFront(&q);
// queuePop(&q);
// if (front)
// //如果剩余元素中存在非空节点,说明节点不连续
// return 0;
// }
// //所有的非空节点都是连续的
// return 1;
//}
void test()
{
char arr[] = "ABD##E#H##CF##G##";
int idx = 0;
BNode* root = creatBtree(arr, &idx);
preOrder(root);
printf("\n");
inOrder(root);
printf("\n");
postOrder(root);
printf("\n");
printf("size: %d \n", bTreeSize1(root));
int count = 0;
bTreeSize2(root, &count);
printf("size: %d \n", count);
printf("Ksize: k-->%d: %d\n", 4, bTreeKSize(root, 4));
BNode* node = bTreeFind(root, 'G');
printf("%p-->%c\n", node, *node);
bTreeDestroy(&root);
}
int main()
{
test();
return 0;
}