/*************************************************************************
> File Name: btree.c
> Author: XXDK
> Email: v.manstein@qq.com
> Created Time: Fri 10 Mar 2017 12:19:59 AM PST
************************************************************************/
#include<stdio.h>
#include"linkqueue.h"
//#include"linkstack.h"
typedef char data_t;
typedef struct btnode {
data_t data;
struct btnode* lchild;
struct btnode* rchild;
}btree_t;
void* assertx(void* p)
{
if(p == NULL) {
printf("argument error\n");
return NULL;
}
}
/**
* @data: 节点数据指针
* @num: 节点位置编号从根1开始
* @len: 待存入树节点中的数据的长度
*/
btree_t* create_btree(data_t* data, int num, int len)
{
btree_t *root;
// 1.
root = (btree_t*)malloc(sizeof(btree_t));
if(root == NULL) {
printf("allocate memory error\n");
return NULL;
}
// 2.
root->data = data[num];
root->lchild = NULL;
root->rchild = NULL;
// 3. 这里利用满二叉树的特性
if(2*num <= len) {
root->lchild = create_btree(data, 2*num, len);
}
if(2*num+1 <= len) {
root->rchild = create_btree(data, 2*num+1, len);
}
return root;
}
// 层次遍历
int btree_travers_layer(btree_t* root)
{
assertx(root);
btree_t* temp;
LinkQueue* queue = create_empty_linkqueue();
// 1. root 入队列
enter_linkqueue(queue, root);
// 2. root 出队列,每出一个,拿到其孩子节点放入队尾
// 直到队列为空,完成遍历
while(!is_empty_linkqueue(queue)) {
temp = delete_linkqueue(queue);
printf("[%c] ", temp->data);
if(temp->lchild != NULL)
enter_linkqueue(queue, temp->lchild);
if(temp->rchild != NULL)
enter_linkqueue(queue, temp->rchild);
}
printf("\n");
}
// 前序遍历
int btree_travers_preorder(btree_t* root)
{
if(root == NULL) {
return -1;
}
printf("[%c] ", root->data);
if(root->lchild != NULL) {
btree_travers_preorder(root->lchild);
}
if(root->rchild != NULL) {
btree_travers_preorder(root->rchild);
}
return 0;
}
// 中序遍历
int btree_travers_midorder(btree_t* root)
{
if(root == NULL) {
return -1;
}
if(root->lchild != NULL) {
btree_travers_midorder(root->lchild);
}
printf("[%c] ", root->data);
if(root->rchild != NULL) {
btree_travers_midorder(root->rchild);
}
return 0;
}
// 后序遍历
int btree_travers_postorder(btree_t* root)
{
if(root == NULL) {
return -1;
}
if(root->lchild != NULL) {
btree_travers_postorder(root->lchild);
}
if(root->rchild != NULL) {
btree_travers_postorder(root->rchild);
}
printf("[%c] ", root->data);
return 0;
}
/*****************************************************
* 计算树的高度
* 思路:
* 用两个队列A,B。第一层节点入A队列,弹出A
* 队列中的元素所有元素,每出一个,判读其左右孩子
* 若果存在孩子,则孩子入B队列。层数累加。然后弹出
* 所有B的元素,同样每出一个,判断左右孩子,存在则
* 入A队列,层数累加。如此直到队列为空。
*****************************************************/
unsigned int count_btree_height(btree_t* root)
{
unsigned int count = 0;
btree_t* temp;
LinkQueue* Aq = create_empty_linkqueue();
LinkQueue* Bq = create_empty_linkqueue();
LinkQueue* Tq;
if(root == NULL) {
return 0;
}
enter_linkqueue(Aq, root);
while(!is_empty_linkqueue(Aq)) { // 判断也就是上一层的孩子构成的队列是否为空
while(!is_empty_linkqueue(Aq)) { // 出队直到整个队列元素都被处理
temp = delete_linkqueue(Aq); //
if(temp->lchild != NULL) {
enter_linkqueue(Bq, temp->lchild);
}
if(temp->rchild != NULL) {
enter_linkqueue(Bq, temp->rchild);
}
}
count++;
Tq = Aq; // 为了简化代码: 交换 Aq和Bq,就是下次操作之前层的孩子队列
Aq = Bq;
Bq = Tq;
}
return count;
}
int main()
{
char ca[] = { 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'};
btree_t* tree = create_btree(ca, 1, sizeof(ca)/sizeof(ca[0]) - 1);
printf("layer travers: ");
btree_travers_layer(tree);
printf("pre travers: ");
btree_travers_preorder(tree);
printf("\n");
printf("mid travers: ");
btree_travers_midorder(tree);
printf("\n");
printf("post travers: ");
btree_travers_postorder(tree);
printf("\n");
printf("btree height: %d\n", count_btree_height(tree));
return 0;
}
这里使用了队列和递归的思维解决问题。
gcc输出:
layer travers: [a] [b] [c] [d] [e] [f] [g] [h] [i] [j] [k] [l] [m] [n]
pre travers: [a] [b] [d] [h] [i] [e] [j] [k] [c] [f] [l] [m] [g] [n]
mid travers: [h] [d] [i] [b] [j] [e] [k] [a] [l] [f] [m] [c] [n] [g]
post travers: [h] [i] [d] [j] [k] [e] [b] [l] [m] [f] [n] [g] [c] [a]
btree height: 4
------------------------------------------------------------------------