5.2 二叉树 算法
咱们写一个二叉树,它支持树的插入,删除,查询和遍历,并且左子树的数据都小于右子树的数据(PS:树实际上很难的,想深刻了解的话,能够去看看<算法导论>,什么红黑树啊,B树啊什么的,反正我没看懂就是了--估计是我太菜了^_^): 数据结构
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct TREE{ int data; struct TREE *leftChild; struct TREE *rightChild; }Tree; void insertTree( Tree *tree, int data ); void deleteTree( Tree *tree, int data ); int searchTree( Tree *tree, int data ); void showTree( Tree *tree ); int main( void ) { Tree *tree = ( Tree * )malloc( sizeof( Tree ) ); tree->leftChild = tree->rightChild = NULL; insertTree( tree, 5 ); insertTree( tree, 3 ); insertTree( tree, 2 ); insertTree( tree, 4 ); insertTree( tree, 8 ); insertTree( tree, 7 ); insertTree( tree, 9 ); insertTree( tree, 6 ); showTree( tree->leftChild ); deleteTree( tree, 3 ); deleteTree( tree, 5 ); deleteTree( tree, 6 ); printf("\n"); showTree( tree->leftChild ); printf("\n"); if ( searchTree( tree, 8 ) ){ printf("8 in the tree\n"); } else{ printf("8 not in the tree\n"); } if ( searchTree( tree, 13 ) ){ printf("13 in the tree\n"); } else{ printf("13 not in the tree\n"); } return 0; } void insertTree( Tree *tree, int data ) { Tree *newTree = ( Tree * )malloc( sizeof( Tree ) ); newTree->leftChild = newTree->rightChild = NULL; newTree->data = data; if ( ( NULL == tree->leftChild ) && ( NULL == tree->rightChild ) ){ tree->leftChild = newTree; } else{ tree = tree->leftChild; while ( NULL != tree ){ if ( data == tree->data ){ return; } else if ( data < tree->data ){ if ( NULL == tree->leftChild ){ tree->leftChild = newTree; return; } tree = tree->leftChild; } else{ if ( NULL == tree->rightChild ){ tree->rightChild = newTree; return; } tree = tree->rightChild; } } } } /* 找到被删除节点的右子树的最小节点,删除最小节点而且将其值赋给被删除的节点 */ void deleteTree( Tree *tree, int data ) { Tree *prevTree = ( Tree * )malloc( sizeof( Tree ) ); //指向删除节点的前一个节点 Tree *tempTree = ( Tree * )malloc( sizeof( Tree ) ); //处理被删除的节点拥有左右树的特殊状况 prevTree = tree; tree = tree->leftChild; while ( tree ){ if ( data < tree->data ){ prevTree = tree; tree = tree->leftChild; } else if ( data > tree->data ){ prevTree = tree; tree = tree->rightChild; } else{ //删除节点的左子树为空,则直接用右子树替换该节点 if ( NULL == tree->leftChild ){ if ( data == prevTree->leftChild->data ){ prevTree->leftChild = prevTree->leftChild->rightChild; } else{ prevTree->rightChild = prevTree->rightChild->rightChild; } } else if ( NULL == tree->rightChild ){ //删除节点的右子树为空,则直接用左子树替换该节点 if ( data == prevTree->leftChild->data ){ prevTree->leftChild = prevTree->leftChild->leftChild; } else{ prevTree->rightChild = prevTree->rightChild->leftChild; } } else{ tempTree = tree; //保存右子树中最小节点的前节点 tree = tree->rightChild; while ( tree->leftChild ){ //找到最小节点 tempTree = tree; tree = tree->leftChild; } //替换数据 if ( data == prevTree->leftChild->data ){ prevTree->leftChild->data = tree->data; } else{ prevTree->rightChild->data = tree->data; } //删除最小节点 if ( tempTree->leftChild->data == tree->data ){ tempTree->leftChild = tree->rightChild; } else{ tempTree->rightChild = tree->rightChild; } } break; } } } int searchTree( Tree *tree, int data ) { tree = tree->leftChild; while ( tree ){ if ( data == tree->data ){ return 1; } else if ( data < tree->data ){ tree = tree->leftChild; } else{ tree = tree->rightChild; } } return 0; } void showTree( Tree *tree ) { if ( tree ){ printf("%d ", tree->data ); showTree( tree->leftChild ); showTree( tree->rightChild ); } }
发现效率有点低@_@ 学习
二叉树有四种遍历方式:前序遍历,中序遍历,后序遍历,层序遍历.其中,层序遍历比较难.因此尝试写下代码看看: .net
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SIZE 100 typedef struct TREE{ int data; struct TREE *leftChild; struct TREE *rightChild; }Tree; Tree *stack[ MAX_SIZE ]; int top = 0; int rear = 0; void insertTree( Tree *tree, int data ); void showTree( Tree *tree ); int main( void ) { Tree *tree = ( Tree * )malloc( sizeof( Tree ) ); tree->leftChild = tree->rightChild = NULL; insertTree( tree, 5 ); insertTree( tree, 3 ); insertTree( tree, 2 ); insertTree( tree, 4 ); insertTree( tree, 8 ); insertTree( tree, 7 ); insertTree( tree, 9 ); insertTree( tree, 6 ); showTree( tree->leftChild ); return 0; } void insertTree( Tree *tree, int data ) { Tree *newTree = ( Tree * )malloc( sizeof( Tree ) ); newTree->leftChild = newTree->rightChild = NULL; newTree->data = data; if ( ( NULL == tree->leftChild ) && ( NULL == tree->rightChild ) ){ tree->leftChild = newTree; } else{ tree = tree->leftChild; while ( NULL != tree ){ if ( data == tree->data ){ return; } else if ( data < tree->data ){ if ( NULL == tree->leftChild ){ tree->leftChild = newTree; return; } tree = tree->leftChild; } else{ if ( NULL == tree->rightChild ){ tree->rightChild = newTree; return; } tree = tree->rightChild; } } } } void showTree( Tree *tree ) { stack[ rear++ ] = tree; while ( 1 ){ tree = stack[ top++ ]; if ( tree ){ printf("%d ", tree->data ); if ( tree->leftChild ){ stack[ rear++ ] = tree->leftChild; } if ( tree->rightChild ){ stack[ rear++ ] = tree->rightChild; } } else{ break; } } }
5.4 二叉树的其余操做 指针
1. 二叉树的复制 code
直接将头指针赋值便可. blog
2. 判断二叉树的等价性 排序
须要用到递归,代码相似以下: 递归
int equal(tree_pointer first, tree_pointer second ) { return ((!first && !second)||(first && second && (first->data == second->data)) && equal(first->left_child, second->left_child) && equal(first->right_child, second->right_child)) }
void swapLeftRight( Tree *tree ) { if ( tree ){ Tree *tempTree = ( Tree * )malloc( sizeof( Tree ) ); tempTree = tree->leftChild; tree->leftChild = tree->rightChild; tree->rightChild = tempTree; swapLeftRight( tree->leftChild ); swapLeftRight( tree->rightChild ); } }
5.5 线索二叉树 队列
线索二叉树经过增长数据结构而简化遍历,这种想法是否可取得进一步讨论.
5.6 堆
1. 最大树是指在树中,一个结点有儿子结点,其关键字都不小于儿子结点的关键字值.最大堆是一棵彻底二叉树,也是一棵最大树.
2. 最小数是指在树中,一个结点有儿子结点,其关键字都不大于儿子结点的关键字值.最小堆是一棵彻底二叉树,也是一棵最小数.
http://my.oschina.net/voler/blog/167320
以前学习算法导论的时候,堆排序作了很详细的笔记.因此这里就再也不重复了(不过有点忘记了.仍是得找段时间好好研究一下算法导论).
5.7 二叉搜索树
这篇文章刚开始的时候就用一个程序开头,就是二叉搜索树的增删查.故再也不重复.