树的基本操作
来源:互联网 发布:注册环保工程师知乎 编辑:程序博客网 时间:2024/05/16 12:36
今天这一章概述树的基本操作,边写边调试边更新!!!
首先定义树的节点结构:
#include<stdio.h>#include <stdlib.h>typedef char ElemType;/*树的结点结构*/typedef struct BiTNode{ElemType data;struct BiTNode * lchild;struct BiTNode * rchild;}BiTNode,* BiTree;
前序遍历构造一颗树,当遇到输入‘#’时表示此结点的前驱为叶子结点:
void CreateTree(BiTree * T){ElemType ch;scanf("%c",&ch);if (ch == '#'){*T = NULL;}else{*T = (BiTree)malloc(sizeof(BiTNode));if(*T ==NULL)abort();(*T)->data = ch;CreateTree(&(*T)->lchild);CreateTree(&(*T)->rchild);}}
三种简单的遍历方法,利用递归做非常简单,树把递归用到了极致:
/*前序遍历*/void PreOrderTraverse(BiTree T){if (!T){return;}printf("%c ",T->data);PreOrderTraverse(T->lchild);PreOrderTraverse(T->rchild);}/*中序遍历*/void InOrderTraverse(BiTree T){if (!T){return;}InOrderTraverse(T->lchild);printf("%c ",T->data);InOrderTraverse(T->rchild);}/*中序遍历*/void PostOrderTraverse(BiTree T){if (!T){return;}PostOrderTraverse(T->lchild);PostOrderTraverse(T->rchild);printf("%c ",T->data);}
层序遍历需要利用之前学过的一个数据结构——队列帮助我们完成,所以我就简单的写了一个队列,只有Push和Pop两个方法:
/******************************简单的队列***********************************/typedef BiTree QueElem;typedef struct Queue{int rear;int front;QueElem * queue;int quesize;}Queue, * pQueue;void Init(pQueue * que, int size){*que = (pQueue)malloc(sizeof(Queue));(*que)->queue=(QueElem*)malloc(sizeof(QueElem)*size);(*que)->front = (*que)->rear = 0;(*que)->quesize=size+1;}void Push(pQueue * que,QueElem e){(*que)->rear=((*que)->rear+1)%(*que)->quesize;(*que)->queue[(*que)->rear] = e;}void Pop(pQueue * que,QueElem * e){(*que)->front=((*que)->front+1)%(*que)->quesize;*e = (*que)->queue[(*que)->front];}/*******************************************************************************/
接下来就是层序遍历的实现,层序遍历比之前增加了点难度,不过很好的帮助我们复习了一下队列的用法,利用队列FIFO的特性,我们也将层序遍历实现了!
/*层序遍历*/void LevelOrderTraverse(BiTree T){if (!T){return;} else{pQueue one;Init(&one,20);Push(&one,T);while (one->rear != one->front){BiTree temp =NULL;Pop(&one,&temp);printf("%c",temp->data);if (temp->lchild){Push(&one,temp->lchild);} if (temp->rchild){Push(&one,temp->rchild);}}}}
下面这个方法是计算树的度,树的度说白了就是树的层数,当然是是从根结点开始遍历加上左子树和右子树中度比较大的数:
/*求树的度*/int Depth(BiTree T){if (!T){return 0;}int left = Depth(T->lchild)+1;int right = Depth(T->rchild)+1;return left > right ? left : right;}
有是一个简单的操作——销毁树,这里有个地方值得注意一下, 为什么参数要用BiTree * T ? 如果不加 * ,最后的*T=NULL 就要改为 T=NULL,这样能不能传递出去呢?
起到防止失控指针的作用了吗?读者可以自己进行调试看看!!!
/*销毁树*/void DestoryTree(BiTree * T){if(*T == NULL){return;}if ((*T)->lchild){DestoryTree(&(*T)->lchild);}if((*T)->rchild){DestoryTree(&(*T)->rchild);}free(*T);*T=NULL; /*注意*/}
这个方法是获取数据域等于e的结点的双亲结点,挺纠结的一个方法,大半夜了脑袋有点不好使,不过经得起测试,结果正确。
为什么 要用参数返回结果呢,因为有大神告诉我,返回值是用来返回调试错误的,而且返回值只能返回一个结果,而参数我们可以返回很多结果,
这也正是我们学习C语言指针的精髓所在!
/*获取e的前驱*/void getParent(BiTree T, ElemType e,BiTree * RES){if ( * RES != NULL || !T){return;}if (T->lchild && * RES == NULL){if (T->lchild->data == e){*RES = T;return;}getParent(T->lchild, e,RES);}if (T->rchild && * RES == NULL){if (T->rchild->data == e){*RES = T;return;}getParent(T->rchild, e,RES);}}
0 0
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 二叉树的基本操作
- 平衡树的基本操作
- JDK中的二分查找算法
- 2014.1.11 C开发窗口程序Combo控件的应用
- C - Count TheCarries
- 《Start Developing iOS Apps Today》学习笔记(三)心得体会
- 点滴:Java Socket编程【转】
- 树的基本操作
- ARM汇编SWI
- cocos2d-x OpenGL Shader 图片特效处理
- hibernate将本地SQL查询结果封装成对象
- ZOJ-2548
- 十步完全理解SQL
- Hadoop项目架构及与其他项目的结合关系
- 编译原理学习笔记01——(通过老外吃中餐—学最基本文法概念)——2014_1_11
- 从汇编层面深度剖析C++虚函数