数据结构之---树(二)

来源:互联网 发布:下载定时开关机软件 编辑:程序博客网 时间:2024/06/06 02:15

二叉树是一棵每个节点都不能有多余2个儿子的树,它的一个重要的性质是平均二叉树的深度要比N小得多,而二叉查找树的深度的平均值是O(logN)。二叉树的定义比较简单

/*二叉树有两个儿子,所以可以直接由根节点指向它们即可*/typedef struct tree_node *ptrnode;typedef struct tree_node *tree;struct tree_node{int element;ptrnode lchild;ptrnode rchild;}/*二叉树结构清晰,分别指向左右孩子即可,当然也可用数组实现,不过指针比较清晰,我采取指针*/
二叉树有很多应用,这里举两个很常见的例子,第一个是表达式树,表达式树是叶节点为操作数,其余节点为操作符的一种树。对其进行中序遍历可以得到一个标准的表达式。(联想:可以用来制作计算器),由于中缀表达式可以很方便的转化为后缀表达式,所以这里讨论一下根据后缀表达式构造一颗表达式树。它的思想是,对输入序列进行扫描,如果为操作数,则进栈,为操作符则弹出两个元素,使它们指向这个新进的元素,同时该元素进栈。

/*其策略为如果为操作数,则进栈,如果为操作符,则弹出两个元素,指向该操作符,将该操作符进栈*/tree create_expression_tree(){char in;stack store;/*这是一个树节点指针类型的栈,用于存储*/while((in=getchar())!=EOF){ptrnode new_node=create_tree_node(in);/*创建一个节点*/if in is operandpush(new_node,store);if in is operator{new_node->rchild=pop(store);new_node->lchild=pop(store);push(new_node,store);}}}/*至此一棵表达式树构造完成*/
还有一个应用的例子是非常出名的二叉查找树,它在查找中很有应用。一棵二叉查找树的平均深度为logN。二叉查找树是左子树的关键字小于该节点,右子树的关键字大于该节点的树,很明显这是一个递归的定义。

对于二叉树进行的操作有创建一棵空树,查找某个元素,查找最大值,查找最小值,删除,插入等。

创建一颗空树make_empty:

tree make_empty(tree T){if(T!=NULL){make_empty(T->lchild);make_empty(T->rchild);free(T);}return NULL;}

查找 find:
ptrnode find(int x,tree T){if(T==NULL)return NULL;if(x<T->element)return find(T->lchild);if(x>T->element)return find(T->rchild);elsereturn T;}

查找最小find_min:

ptrnode find_min(tree T){if(T==NULL)return NULL;elseif(T->lchild==NULL)return T;elsereturn find_min(T->lchild);}

查找最大find_max:

ptrnode find_max(tree T){if(T==NULL)return NULL;elseif(T->rchild==NULL)return T;elsereturn find_max(T->rchild);}/*当然完全不用使用递归,使用递归是为了让结构更加清晰*/

插入操作:

tree insert(int x,tree T){if(T==NULL){T=(tree)malloc(sizeof(struct tree_node));T->element=x;T->lchild=NULL;T->rchild=NULL;}elseif(x<T->element)T->lchild=insert(x,T->lchild);elseif(x>T->element)T->rchild=insert(x,T->rchild);return T;}/*注意到如果x相等的话,我们什么也不做*/

最后是删除操作,几乎在所有结构中删除都是比较麻烦的,注意到删除一个元素后,可以用它右子树的最小节点来填充(或者左子树的最大),然后递归删除即可

tree delete(int x,tree T){if(T==NULL)Error("not found");elseif(x<T->element)T->lchild=delete(x,T->lchild);elseif(x>T->element)T->rchild=delete(x,T->rchild);else/*找到了*/{if(T->lchild&&T->rchild)/*拥有两个孩子*/{ptrnode temp;temp=find_min(T->rchild);T->element=temp->element;T->rchild=delete(temp->element,T->rchild);}else/*只有一个孩子*/{if(T->lchild==NULL)T=T->rchild;if(T->rchild==NULL)T=T->lchild;}}return T;}/*注意到为了保持程序易读,后面进行了两次遍历,效率并不高。当然这很容易改进*/

树还有很多像什么AVL树,B树,伸展树等等。这里推荐一本数据结构的书籍,严的那本很多人推荐,我也看过,不过个人觉得他的讲法并不是很好,分析也不够透彻。推荐一本老外的吧:data structures and algorithom analysis in c。不得不说,老外很多书都很经典的,这本也是很多一线高校的教材,英语好的话可以挑战一下原版。


0 0
原创粉丝点击