二叉树

注:以下代码以及总结都来自个人,完整代码链接:https://github.com/xuatcc/binary-tree.git
······················20170909·························
二叉树的结构定义:
typedef char elem_type;
typedef struct bt_node
{
 struct bt_node *parent;
 struct bt_node *leftchild;
 struct bt_node *rightchild;
 elem_type data;
}bt_node;
bt_node * creat();      //根据终端输入的前序遍历  (例如://ABC##DE##F##G#H##    //用井号代替空结点,构造一颗完全二叉树) 创建二叉树  
bt_node * creatfi(char *fs, char *is);     //根据中序和前序遍历  创建二叉树
/*
 根据前序和中序创建二叉树
 1、通过先序遍历找到根结点A,再通过A在中序遍历的位置找出左子树,右子树
 2、在A的左子树中,找左子树的根结点(在先序中找),转步骤1
 3、在A的右子树中,找右子树的根结点(在先序中找),转步骤1
 */

bt_node * creatil(char *is, char *ls);       //根据中序和后续遍历  创建二叉树
// 前序和后序创建不出 二叉树,无法判断二叉树根节点的左右子树部分
//留下问题:如果结点重复如何创建???
void  inorder(bt_node *ptr);   //根据二叉树  打印中序遍历结果
void  firstorder(bt_node *ptr);     //前序遍历
void lastorder(bt_node *ptr);      //后序遍历
int levelorder(bt_node *ptr);    // 层次遍历       //层次遍历需要用到 队列,在队列不为空的前提下循环,左右孩子都不为空,就入队列。
void print_k_level(bt_node *ptr, int k);   //打印第k层
/*
非递归的先序遍历
我的算法思想:
两个循环嵌套   外层循环 :当结点的右子树不为空  将右子树入栈  循环的结束条件是 栈不为空
内层循环 :遍历打印结点的左子树    循环结束条件是 结点至少有一个分支
*/

int while_firstorder(bt_node *ptr);
/*
非递归的中序遍历:
  先根左子树遍历,依次入栈, 如果遇到左子树为空,出栈根元素,入栈右子树  ,
       如果遇到右子树为空,出栈上一个的根元素,入栈上一个根元素的右子树
*/

int while_inorder(bt_node *ptr);
/*
非递归的后序遍历  :
 用一个作为访问过结点的标记指针 bt_node *tag
 先不打印根节点  如果根节点的右子树被访问过   ptr->rightchild==tag  打印根节点
*/

int while_lastorder(bt_node *ptr);

bt_node *findvalue(bt_node *root, elem_type value);     //  在二叉树中 查找值
bt_node *findparent(bt_node *root, bt_node *child);       //  查找某个孩子节点的双亲结点
bt_node *Find_Parent(bt_node *root, bt_node*child);        //将递归的函数 封装
int  node_number(bt_node *ptr);    //计算所有结点的个数
int  leafnode_number(bt_node *ptr);      //计算叶子结点的个数
int node_has_twochild_number(bt_node *ptr);  //计算包含两个分支的结点个数
int node_has_onechild_number(bt_node *ptr);  //计算包含一个分支的结点个数
int depth(bt_node *root);    //计算二叉树的深度

······················20170910·························   
bt_node *find_near_common_parent(bt_node *root, bt_node *node1, bt_node *node2);//寻找两个子结点的共同的最近的父节点
/*
找两个孩子结点 最近的 共同的  父结点
我的思路是: 用两个队列保存孩子结点的父结点 以及父节点的父结点 一直循环直到根节点
   然后比较两个队列里的元素  第一个相等的元素  即为最近的 共同双亲结点
*/

······················20170923·························
关于定义:
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
 (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
 (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
 (3)左、右子树也分别为二叉排序树;
一个深度为k,节点个数为 2 ^ k - 1 的二叉树为满二叉树。
一颗深度为k二叉树,有n个节点,然后,也对这棵树进行编号,如果所有的编号都和满二叉树对应,那么这棵树是完全二叉树。
平衡二叉搜索树(Balanced Binary Tree)具有以下性质:
 它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
 常用算法有红黑树、AVL、Treap、伸展树等。
 在平衡二叉搜索树中,我们可以看到,其高度一般都良好地维持在O(log(n)),大大降低了操作的时间复杂度。

bool is_complete_tree(bt_node *root);   //是否是完全二叉树
/*
判断是否是完全二叉树  思想:
 对一颗二叉树,计算它的深度
 对同样深度的满二叉树   做层次遍历
 如果遇到空  但队列之后仍有元素   则不是完全二叉树
*/

bool is_full_tree(bt_node *root);   //是否是满二叉树
/*
 一个深度为k,节点个数为 2 ^ k - 1 的二叉树为满二叉树。
*/

bool is_balance_tree(bt_node * root);         //是否是平衡二叉树
bool is_bstree(bt_node *root);  //是否是二叉排序树

······················20170924·························
/*
 线索化二叉树 的数据结构是一个五元组 
 包含指向左子树 右子树的指针
 以及标志左右指针到底是指向 左右孩子还是 遍历序列的前驱后继 标志位
 以及数据域
*/
作业的顺序:
带井号的先序遍历-》创建一颗5元组的二叉树-》中序线索化二叉树-》中序遍历-》逆置中序遍历
        先序线索化二叉树    非递归的先序遍历
        后序线索化二叉树    非递归的后序遍历

typedef char elem_type;
#define END  '#'
typedef enum{link=0,thread=1}pointtag;
线索化二叉树结构定义:
typedef struct thread_btree
{
 struct thread_btree *leftchild;
 struct thread_btree *rightchild;
 pointtag ltag, rtag;
 elem_type data;
}thread_btree;
/*
在编程过程中遇到一个新手比较郁闷的问题,在创建二叉树的时候,需要传递一个字符串序列,
但是字符串序列在递归过程中,只能通过地址传递才能记录递归时的指针位置
这时候老杨用到了我还不是特别理解的引用,函数定义时形参可以加一个引用,表示一个常性的指针,
但是在函数的申明时,形参不加这个引用。(会引起语法错误 ,但是为什么呢)
于是要把这个带引用的函数再封装起来。
*/
thread_btree *creat_thrtree_byf();//根据带井号的先序创建二叉树
thread_btree * creat_thrtree_fi(char *fs, char *is);//根据先序中序遍历创建二叉树
void inorder_thrtree(thread_btree *ptr);  //中序遍历此二叉树  检验是否创建成功
void make_thread_tree_by_inorder(thread_btree *ptr);//将这颗二叉树 线索化  按照中序遍历的结果

void make_by_inorder(thread_btree *ptr, thread_btree *&p)
{
 if (ptr != NULL)
 {
  make_by_inorder(ptr->leftchild, p);
  if (ptr->leftchild == NULL)
  {
   ptr->leftchild = p;
   ptr->ltag = thread;
  }
  if (p != NULL && p->rightchild == NULL)
  {
   p->rightchild = ptr;
   p->rtag = thread;
  }
  p = ptr;
  make_by_inorder(ptr->rightchild, p);
 }
}
void make_thread_tree_by_inorder(thread_btree *ptr)//将这颗二叉树 线索化  按照中序遍历的过程
{
 thread_btree *p = NULL;
 make_by_inorder(ptr, p);
 p->rightchild = NULL;
 p->rtag = thread;
}

void make_thread_tree_by_firstorder(thread_btree *ptr);//将这颗二叉树 线索化  按照先序遍历的结果
void make_thread_tree_by_lastorder(thread_btree *ptr);//将这颗二叉树 线索化  按照后序遍历的结果
thread_btree *First(thread_btree *p);
thread_btree * Next(thread_btree *p);
void thr_inorder(thread_btree *ptr);//中序遍历此线索二叉树
void thr_firstorder(thread_btree *ptr);//先序遍历此线索化二叉树
void thr_lastorder(thread_btree *ptr);//后序遍历此线索化二叉树   // 不会写

thread_btree *Last(thread_btree *p);
thread_btree* Prev(thread_btree *p);
void thr_inorder_res(thread_btree *ptr);//逆序打印中序遍历


······················20170931·························
完全二叉树 :拿数组存放
                      父子之间在数组内的关系: 父节点:i   左孩子:2*i+1   右孩子: 2*i+2
满二叉树 同上
非完全二叉树:拿数组存放
                        必须构造成完全二叉树,用空格或者空或者井号 占位

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值