数据结构5-二叉树

二叉树大量用到递归思想

1.二叉树的概念 

1.树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树(有且仅有一个根结点)
2.二叉树的子节点分为左节点右节点。 二叉树最多有两个子树(左右子树)
3.如果该二叉树的所有叶子节点都在最后一层,并且结点总数= 2^n -1 , n 为层数,则我们称为满二叉树
4.如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树

二叉树的五种形态:

1、 空二叉树(什么都没有,nothing)
2、 只有一个根节点的二叉树(左右子树为空)
3、 右子树为空的二叉树(右腿断了)
4、 左子树为空的二叉树(左腿断了)
5、 左右子树都非空的的二叉树(既有左子树又有右子树,)

2.创建并遍历二叉树

先序遍历: 先访问父节点(根结点) -----> 先序遍历左子树   ------> 先序遍历右子树  (递归调用)
中序遍历: 先中序遍历左子树,再输出父节点再中序遍历右子树
后序遍历: 先后遍历左子树,再后序遍历右子树,最后输出父节点
小结
: 看输出父节点的顺序,就确定是前序,中序还是后序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 二叉树节点
struct BinTree_node
{
        unsigned char elem;
        struct BinTree_node *ltree, *rtree;
};

// 声明
struct BinTree_node *create_bintree(void);
void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree)
// 主函数
int main(void)
{      
	struct BinTree_node *mytree;
	mytree = create_bintree();
    // pre_order(mytree);
    // in_order(mytree);
    pos_order(mytree);
    printf("\n");
	return 0;
}

// 创建树
struct BinTree_node *create_bintree(void)
{
	unsigned char flag;
	struct BinTree_node *tree;

    tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
	printf("please input the mode elem:\n");
	while((tree->elem = getchar()) == '\n');
    //左子树
	printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
	while((flag = getchar()) == '\n');     //避免连续getchar(),该方法避免回车
    if(flag == 'Y')
		tree->ltree = create_bintree();  //递归创建左子树
    else
		tree->ltree = NULL;
    //右子树
	printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
    while((flag = getchar()) == '\n');     //避免连续getc har(),该方法避免回车
    if(flag == 'Y')
         tree->rtree = create_bintree();  //递归创建左子树
    else
         tree->rtree = NULL;
    return tree;
}

// 先序遍历函数  ABDECFG

void pre_order(struct BinTree_node *tree)
{
     if(tree)
     {
          printf("%c", tree->elem);
          pre_order(tree->ltree);
          pre_order(tree->rtree);
     }
}

// 中序遍历函数   DBEAFGC

void in_order(struct BinTree_node *tree)
{
     if(tree)
     {
          in_order(tree->ltree);
          printf("%c", tree->elem);
          in_order(tree->rtree);
     }
}

// 后序遍历函数  DEBGFCA
void pos_order(struct BinTree_node *tree)
{
     if(tree)
     {
          pos_order(tree->ltree);
          pos_order(tree->rtree);
          printf("%c", tree->elem);
     }
}

3.遍历二叉树(层次遍历) 

层次遍历即为从上到下,从左到右依次访问二叉树的每个结点。

实现思路
(1)我们定义一个队列,先将根结点入队
(2)当前结点是队头结点,将其出队并访问;
(3)若当前结点的左结点不为空将左结点入队;若当前结点的右结点不为空将其入队即可。

只要队列不为空
{
                  队列头出队列
                  打印节点数据域
                  如果有左子树
                               左子树节点入队列
                  如果有右子树
                               右子树节点入队列   --------》再次循环
}

例图

queue.h

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <stdio.h>
#include "binary_tree.h"   //包含二叉树

# define SIZE 512    // 宏定义

//函数声明
int is_empty(void);
int is_full(void);
void enqueue(struct BinTree_node c);
struct BinTree_node dequeue(void);


#endif

queue.c

# include "queue.h"
 
struct BinTree_node queue[SIZE];
int head = 0, tail = 0;
 
//循环队列入队
void enqueue(struct BinTree_node c)
{
	queue[tail] = c;
	tail = (tail+1) % SIZE;
}
//出队
struct BinTree_node dequeue(void)
{
	struct BinTree_node ch;
	ch = queue[head];
	head = (head + 1) % SIZE;
    return ch;
}
//判断队列是否为空
int is_empty(void)
{
	return head == tail;
}
//判断队列为满
int is_full(void)
{
    return (tail + 1) % SIZE == head;
 
}

binary_tree.h

#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__

#include <stdio.h>
#include <stdlib.h>
        // enqueue(struct BinTree_node c);
 
// 二叉树节点
struct BinTree_node
{
        unsigned char elem;
        struct BinTree_node *ltree, *rtree;
};

#include "queue.h"   

// 声明
struct BinTree_node *create_bintree(void);
void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree);
void level_traverse(struct BinTree_node *tree);

#endif

binary_tree.c

#include "binary_tree.h"

// 创建树
struct BinTree_node *create_bintree(void)
{
	unsigned char flag;
	struct BinTree_node *tree;

    tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
	printf("please input the mode elem:\n");
	while((tree->elem = getchar()) == '\n');
    //左子树
	printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
	while((flag = getchar()) == '\n');     //避免连续getchar(),该方法避免回车
    if(flag == 'Y')
		tree->ltree = create_bintree();  //递归创建左子树
    else
		tree->ltree = NULL;
    //右子树
	printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
    while((flag = getchar()) == '\n');     //避免连续getc har(),该方法避免回车
    if(flag == 'Y')
        tree->rtree = create_bintree();  //递归创建左子树
    else
        tree->rtree = NULL;
    return tree;
}

// 先序遍历函数  ABDECFG

void pre_order(struct BinTree_node *tree)
{
     if(tree)
     {
          printf("%c", tree->elem);
          pre_order(tree->ltree);
          pre_order(tree->rtree);
     }
}

// 中序遍历函数   DBEAFGC
void in_order(struct BinTree_node *tree)
{
     if(tree)
     {
          in_order(tree->ltree);
          printf("%c", tree->elem);
          in_order(tree->rtree);
     }
}

// 后序遍历函数  DEBGFCA
void pos_order(struct BinTree_node *tree)
{
     if(tree)
     {
          pos_order(tree->ltree);
          pos_order(tree->rtree);
          printf("%c", tree->elem);
     }
}

void level_traverse(struct BinTree_node *tree)
{
        struct BinTree_node node; //接收出队的队列头
        enqueue(*tree);
        while(!is_empty())
        {
             node = dequeue();
             printf("%c", node.elem);
             if(node.ltree)
             {
                 enqueue(*node.ltree);
             }
             if(node.rtree)
             {
                 enqueue(*node.rtree);
             }
        }
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "binary_tree.h"

// 主函数
int main(void)
{      
	struct BinTree_node *mytree;
	mytree = create_bintree();
    //层次遍历
    level_traverse(mytree);
    printf("\n");
	return 0;
}


//输出  ABCDEFG

4.统计二叉树的深度,叶子数,节点数

二叉树的深度:层数             
(1) 二叉树为空 -------->深度为0 
(2) 一般二叉树深度 =  左右字树最大深度 + 1 
二叉树的叶子数:最低节点数
(1) 二叉树为空 -------->叶子数为0 
(2) 二叉树只有根结点 ,没有左右子树 --------> 叶子数 1 
(3) 一般情况下,左子树叶子数 +  右子树叶子数
二叉树节点个数:
(1) 二叉树为空 -------->节点数为0 
(2) 一般情况下,左子树节点数 +  右子树节点数

queue.h

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <stdio.h>
#include "binary_tree.h"   //包含二叉树

# define SIZE 512    // 宏定义

//函数声明
int is_empty(void);
int is_full(void);
void enqueue(struct BinTree_node c);
struct BinTree_node dequeue(void);


#endif

queue.c

# include "queue.h"
 
struct BinTree_node queue[SIZE];
int head = 0, tail = 0;
 
//循环队列入队
void enqueue(struct BinTree_node c)
{
	queue[tail] = c;
	tail = (tail+1) % SIZE;
}
//出队
struct BinTree_node dequeue(void)
{
	struct BinTree_node ch;
	ch = queue[head];
	head = (head + 1) % SIZE;
    return ch;
}
//判断队列是否为空
int is_empty(void)
{
	return head == tail;
}
//判断队列为满
int is_full(void)
{
    return (tail + 1) % SIZE == head;
 
}

binary_tree.h

#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__

#include <stdio.h>
#include <stdlib.h>
        // enqueue(struct BinTree_node c);
 
// 二叉树节点
struct BinTree_node
{
        unsigned char elem;
        struct BinTree_node *ltree, *rtree;
};

#include "queue.h"   

// 声明
struct BinTree_node *create_bintree(void);
void pre_order(struct BinTree_node *tree);
void in_order(struct BinTree_node *tree);
void pos_order(struct BinTree_node *tree);
void level_traverse(struct BinTree_node *tree);
unsigned int depth(struct BinTree_node *tree);
unsigned int leaf_num(struct BinTree_node *tree);
unsigned int node_num(struct BinTree_node *tree);
#endif

binary_tree.c

#include "binary_tree.h"

// 创建树
struct BinTree_node *create_bintree(void)
{
	unsigned char flag;
	struct BinTree_node *tree;

    tree = (struct BinTree_node *)malloc(sizeof(struct BinTree_node));
	printf("please input the mode elem:\n");
	while((tree->elem = getchar()) == '\n');
    //左子树
	printf("do you want to insert l_tree for %c, (Y/N)?\n", tree->elem);
	while((flag = getchar()) == '\n');     //避免连续getchar(),该方法避免回车
    if(flag == 'Y')
		tree->ltree = create_bintree();  //递归创建左子树
    else
		tree->ltree = NULL;
    //右子树
	printf("do you want to insert r_tree for %c, (Y/N)?\n", tree->elem);
    while((flag = getchar()) == '\n');     //避免连续getc har(),该方法避免回车
    if(flag == 'Y')
         tree->rtree = create_bintree();  //递归创建左子树
    else
         tree->rtree = NULL;
    return tree;
}

// 先序遍历函数  ABDECFG

void pre_order(struct BinTree_node *tree)
{
     if(tree)
     {
          printf("%c", tree->elem);
          pre_order(tree->ltree);
          pre_order(tree->rtree);
     }
}

// 中序遍历函数   DBEAFGC
void in_order(struct BinTree_node *tree)
{
     if(tree)
     {
          in_order(tree->ltree);
          printf("%c", tree->elem);
          in_order(tree->rtree);
     }
}

// 后序遍历函数  DEBGFCA
void pos_order(struct BinTree_node *tree)
{
     if(tree)
     {
          pos_order(tree->ltree);
          pos_order(tree->rtree);
          printf("%c", tree->elem);
     }
}

void level_traverse(struct BinTree_node *tree)
{
        struct BinTree_node node; //接收出队的队列头
        enqueue(*tree);
        while(!is_empty())
        {
             node = dequeue();
             printf("%c", node.elem);
             if(node.ltree)
             {
                 enqueue(*node.ltree);
             }
             if(node.rtree)
             {
                 enqueue(*node.rtree);
             }
        }
}

//计算二叉树深度
unsigned int depth(struct BinTree_node *tree)
{
       unsigned int l_depth;
       unsigned int r_depth;
       if(tree == NULL)
	      return 0;
       else
       {
	       l_depth = depth(tree->ltree);
	       r_depth = depth(tree->rtree);
	       return (l_depth > r_depth) ? (l_depth + 1) : (r_depth + 1);
       }
}

//计算二叉树叶子数
unsigned int leaf_num(struct BinTree_node *tree)
{
       if(tree == NULL)
               return 0;
       else if((tree->ltree ==NULL) && (tree->rtree ==NULL))
               return 1;
       else
               return leaf_num(tree->ltree) + leaf_num(tree->rtree); 
}

//计算二叉树节点数
unsigned int node_num(struct BinTree_node *tree)
{
      if(tree == NULL)
               return 0;
      else
               return  node_num(tree->ltree) +  node_num(tree->ltree) + 1;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "binary_tree.h"

// 主函数
int main(void)
{      
	    struct BinTree_node *mytree;
	    mytree = create_bintree();
        //层次遍历
        level_traverse(mytree);
        printf("\n");
        printf("depth = %d\n", depth(mytree));   // 二叉树深度
        printf("leaf_num = %d\n", leaf_num(mytree));   // 叶子数
        printf("\n");
        printf("node_num = %d\n", node_num(mytree));   // 叶子数
        printf("\n");
	    return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_44177768/article/details/127462564