当前位置:   article > 正文

二叉树(C语言)_c语言create()

c语言create()

1、二叉树的结构

        二叉树是由一个储存数据的变量和两个指向子树的指针构成的,定义在一个结构体中。其一般形式为:

  1. typedef struct BiTree
  2. {
  3. char data;
  4. struct BiTree *lchild;
  5. struct BiTree *rchild;
  6. }BiTree,*BiNode;

        BiNode即结构体变量的指针,BiTree是结构体变量。在创建二叉树时,为每个结点动态分配内存时要用到这两个标识符,例如: BiNode root=(BiNode)malloc(sizeof(BiTree))。

2、二叉树的建立

        二叉树一般使用递归的方式建立,递归调用函数来创建自己的左右子树。

  1. BiNode create()//先序建立二叉树
  2. {
  3. BiNode T;
  4. char a;
  5. scanf("%c",&a);
  6. if(a=='.') return NULL;//当输入.时表示这个结点为空,而且没有左右子树。
  7. else
  8. {
  9. T=(BiNode)malloc(sizeof(BiTree));//动态分配内存
  10. T->data=a;
  11. T->lchild=create();//创建左子树
  12. T->rchild=create();//创建右子树
  13. }
  14. return T;
  15. }

          若想中序或后序创建,则只需改变函数中        T->data=a;        T->lchild=create();        T->rchild=create(); 这三条语句的顺序,先给T->data=a在先的话是先序,在中间的话是中序,在最后的话是后序。

3、二叉树的遍历

        二叉树一般有4种遍历方法,即先序、中序、后序、层序。

        先序的遍历顺序是根节点->左子树->右子树。

        中序的遍历顺序是左子树->根节点->右子树。

        后序的遍历顺序是右子树->根节点->左子树。

        层序的遍历顺序是按层顺次遍历。

        先序、中序、后序的代码基本相同

  1. void pre(BiNode root)//先序遍历二叉树
  2. {
  3. if(root)
  4. {
  5. printf("%c ",root->data);
  6. pre(root->lchild);
  7. pre(root->rchild);
  8. }
  9. }
  10. void mid(BiNode root)//中序遍历二叉树
  11. {
  12. if(root)
  13. {
  14. mid(root->lchild);
  15. printf("%c ",root->data);
  16. mid(root->rchild);
  17. }
  18. }
  19. void post(BiNode root)//后序遍历二叉树
  20. {
  21. if(root)
  22. {
  23. post(root->lchild);
  24. post(root->rchild);
  25. printf("%c ",root->data);
  26. }
  27. }

        例如这个简单的二叉树:

图1

        当我们先序建立二叉树时,应输入:ABDF..GH..I..E..C..,这三种遍历的结果为:

        而层序遍历较为复杂,可以用队列来实现,队列的特点是先进先出。我们先构造一个队列,先将根节点入队列,之后每个出队列的结点都要判断其左右子树是否存在,若存在则入队列。代码如下:

  1. void level(BiNode root)//二叉树的层次遍历,运用队列,每层的结点挨个先进先出。
  2. {
  3. BiNode queue[20],pTemp;
  4. int cur=0,pre=0;//cur表示当前入队列的结店,pre表示当前出队列的结点
  5. queue[cur++]=root;
  6. while(cur!=pre)
  7. {
  8. pTemp=queue[pre++];
  9. printf("%c ",pTemp->data);
  10. if(pTemp->lchild!=NULL) queue[cur++]=pTemp->lchild;
  11. if(pTemp->rchild!=NULL) queue[cur++]=pTemp->rchild;
  12. }
  13. }

        层序遍历上面的二叉树的运行结果为:

4、特殊二叉树

  1、二叉排序树

    1.1 特点及构造方法

        二叉排序树的特点是:若一个结点的左子树非空,则左子树的值一定小于结点的值;若一个节点的右子树非空,则右子树的值一定大于结点的值。

        例如这颗简单二叉排序树:

  

        其创建过程也不复杂,对于每个数据,都判断它与根节点的大小关系,若大于根节点,则作为根节点的右子树,若小于根节点,则作为根节点的左子树。则二叉排序树的中序遍历一定是严格递增的。代码如下:

  1. BiNode BSTInsert(BiNode T,int key)
  2. {
  3. if(!T)//若为空,则创建这个结点
  4. {
  5. T=(BiNode)malloc(sizeof(BiTree));
  6. T->data=key;
  7. T->lchild=T->rchild=NULL;
  8. }
  9. else
  10. {
  11. if(T->data<key)
  12. T->rchild=BSTInsert(T->rchild,key);
  13. else if(T->data>key)
  14. T->lchild=BSTInsert(T->lchild,key);
  15. }
  16. return T;
  17. }
  18. BiNode Insert(BiNode T,int data[],int n)
  19. {
  20. int i;
  21. for(i=0;i<n;i++)
  22. T=BSTInsert(T,data[i]);
  23. return T;
  24. }
  25. int main()
  26. {
  27. int num[9]={8,3,10,13,14,1,6,7,4};
  28. BiNode T=NULL;
  29. T=Insert(T,num,9);
  30. printf("\n中序遍历:");
  31. mid(T);
  32. return 0;
  33. }

        将一个数组{8,3,10,13,14,1,6,7,4}作为数据构造一棵二叉排序树,可以得到上图中的结果,对他进行中序遍历的结果为:

        得到了正确的结果。也可以在二叉排序树构造成功后直接使用BSTInsert函数来插入元素,例如在上面的例子里插入5:

  1. int main()
  2. {
  3. int num[9]={8,3,10,13,14,1,6,7,4};
  4. BiNode T=NULL;
  5. T=Insert(T,num,9);
  6. printf("中序遍历:");
  7. mid(T);
  8. BSTInsert(T,5);
  9. printf("\n插入后:");
  10. mid(T);
  11. return 0;
  12. }

        运行结果为:

    1.2 二叉排序树的查找

        根据二叉树的特点,我们可以轻松的找出二叉排序树中的最小、最大元素和特定元素。

        寻找最小、最大元素的方法是相同的。根据二叉树的特点,若左右子树不为空,则根节点的值一定大于左子树的值、小于右子树的值,那么这棵树的根节点的最左子树和最右子树即为最小、最大元素。代码如下:

  1. BiNode Searchmin(BiNode T)//寻找二叉排序树中的最小元素
  2. {
  3. if(T==NULL)
  4. return NULL;
  5. if(T->lchild==NULL)
  6. return T;
  7. else return Searchmin(T->lchild);//不断搜索他的左子树
  8. }
  9. BiNode Searchmax(BiNode T)//寻找二叉排序树中的最大元素
  10. {
  11. if(T==NULL)
  12. return NULL;
  13. if(T->rchild==NULL)
  14. return T;
  15. else return Searchmax(T->rchild);//不断搜索他的右子树
  16. }

        而查找特定元素也利用了排序树的特点。将结点的值与待查值做比较,若结点值大,则说明待查值在结点的左子树;若结点值小,则说明待查值在结点的右子树,然后递归或不递归地查询结点的左子树或右子树即可。递归查询的代码如下:

  1. BiNode Search_1(BiNode T,int key)//递归查找特定元素
  2. {
  3. if(T==NULL)
  4. return NULL;
  5. if(key>T->data)
  6. return Search_1(T->rchild,key);//查找右子树
  7. else if(key<T->data)
  8. return Search_1(T->lchild,key);//查找左子树
  9. else return T;//找到则返回指针
  10. }

        在此基础上,我们可以省掉递归过程,用while循环来实现结点的遍历。非递归查找代码如下:

  1. BiNode Search_2(BiNode T,int key)//非递归查找特定元素
  2. {
  3. BiNode p=T;
  4. while(p)
  5. {
  6. if(p->data==key)//找到就返回结点
  7. return p;
  8. else p=(p->data>key)?p->lchild:p->rchild;//判断下一个要查找的是左子树还是右子树。
  9. }
  10. return NULL;//找不到则返回空
  11. }

    1.3 删除二叉排序树的一个特定结点

        对于一般的二叉树来说,删去树中的一个结点是没有意义的,因为它将使以被删除的结点为根的子树变成森林,破坏了整棵树的结构。但是,对于二叉排序树,删去树上的一个结点相当于删去有序序列中的一个记录,只要在删除某个结点后不改变二叉排序树的特性即可。

        删除节点p的一般过程是:

        1、在二叉排序树中找到要删除的那个结点p。

        2、若p有左子树,则找到左子树的最右子树r,用r来代替p,将r的左子树作为r父亲的右子树。

        3、若p没有左子树,则用p的右子树r代替p。

        第一步我们可以用一个函数,先根据二叉排序树的特点找到要删除的结点。找到后,用另一个函数来实现第二步或第三步。

        明确思路后,应考虑如何完成用r代替p这一操作,若移动r和p的指针,不仅麻烦,而且移来移去容易出错。仔细思考一下,我们删除的实质上是r,并不是p,则更好的办法是将r的值赋给p,然后删除掉r结点。代码如下:

  1. BiNode Delete(BiNode T,int key)//删除二叉排序树中的特定元素
  2. {
  3. if(T->lchild)//如果存在左子树
  4. {
  5. BiNode p=T->lchild;
  6. BiNode parent=T->lchild;
  7. while(p->rchild!=NULL)//找到左子树的最右子树
  8. {
  9. parent=p;
  10. p=p->rchild;
  11. }
  12. T->data=p->data;//将要删除的结点的值覆盖掉
  13. if(parent!=p)//如果找到的最右子树不是T的左子树,则把最他的左子树作为他的父结点的右子树
  14. parent->rchild=p->lchild;
  15. else T->lchild=p->lchild;//否则T的左子树指向p的左子树
  16. free(p);//清空p的内存
  17. return T;
  18. }
  19. else//如果不存在左子树,则直接返回自己的右子树。
  20. {
  21. BiNode p=T->rchild;
  22. free(T);
  23. return p;
  24. }
  25. }
  26. BiNode DeleteBST(BiNode T,int key)//二叉排序树的删除
  27. {
  28. if(T)
  29. {
  30. if(T->data==key)//若找到要删除的结点,则执行删除操作
  31. T=Delete(T,key);
  32. else if(T->data>key)
  33. T->lchild=DeleteBST(T->lchild,key);
  34. else T->rchild=DeleteBST(T->rchild,key);
  35. }
  36. return T;
  37. }

        用{8,3,10,13,14,1,6,7,4}来测试一下这段代码:

        完全符合预期。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/233202
推荐阅读
相关标签
  

闽ICP备14008679号