1.二叉树
1. 定义:
是每个节点最多只能有两个儿子的树。
2.应用
查找树:所有节点左小右大
平衡树:左右子树深度差1
判定数:分支查找树(例如12个球如何只称3次就能分出轻重)
带权树:路径带权
最优树:带权路径长度最短的树,通信中的压缩编码
2.查找二叉树
1.定义
为每个节点指定一个关键值,每个节点的左子树的关键值都小于节点的关键值,而右子树的关键值都大于节点的关键值。
或者是一颗空树,或者是具有如下性质的非空二叉树:
(1)若左子树不为空,左子树的所有结点的值均小于根的值;
(2)若右子树不为空,右子树的所有结点均大于根的值;
(3)它的左右子树也分别为二叉排序树。
平均深度为O(logN)。
2. 查找二叉树的实现
1.fatal.h
#include <stdio.h> #include<stdlib.h> #define Error(str) FatalError(str) #define FatalError(str) fprintf(stderr,"%s ",str),system("pause"),exit(1)
2.searchtree.h
#include<stdio.h> typedef int ElementType; #ifndef _Tree_H struct TreeNode; typedef struct TreeNode *Position; typedef struct TreeNode *SearchTree; SearchTree MakeEmpty(SearchTree T); Position Find(ElementType X, SearchTree T); Position FindMin(SearchTree T); Position FindMax(SearchTree T); SearchTree Insert(ElementType X, SearchTree T); SearchTree Delete(ElementType X, SearchTree T); ElementType Retrieve(Position P); void Preorder(SearchTree T); #endif
3.searchtree.c
#include "searchtree.h" #include "fatal.h" #include <stdio.h> #include <stdlib.h> struct TreeNode { ElementType Element; SearchTree Left; SearchTree Right; }; SearchTree MakeEmpty(SearchTree T) { if (T!=NULL) { MakeEmpty(T->Left); MakeEmpty(T->Right); free(T); } return NULL; }
/*
在二叉排序树b中查找x的过程为:
- 若b是空树,则搜索失败,否则:
- 若x小于b的根节点的数据域之值,则搜索左子树;否则:
- 若x大于b的根节点的数据域之值,则搜索右子树;否则:
- x等于b的根节点数据域的值,查找成功。
*/ Position Find(ElementType X, SearchTree T) { if (T==NULL) { return NULL; } if (X < T->Element) { return Find(X, T->Left); } else if (X > T->Element) { return Find(X, T->Right); } else { return T; } } Position FindMin(SearchTree T) { if (T == NULL) { return NULL; } else if (T->Left == NULL) { return T; } else { return FindMin(T->Left); } } Position FindMax(SearchTree T) { //if (T == NULL) //{ // return NULL; //} //else if (T->Right == NULL) //{ // return T; //} //else //{ // return FindMax(T->Right); //} if (T != NULL) { while (T->Right != NULL) { T = T->Right; } } return T; } ElementType Retrieve(Position P) { return P->Element; }
/*
向一个二叉排序树b中插入一个结点s,过程为:
- 若b是空树,则将s所指结点作为根结点插入,否则:
- 若s->data小于b的根结点的数据域之值,则把s所指的节点插入到左子树,否则:
- 若s->data大于b的根结点的数据域之值,则把s所指结点插入到右子树中,否则:
- 把s->data等于根节点的数据域的值,已经存在,什么也不做。
*/ SearchTree Insert(ElementType X, SearchTree T) { if (T == NULL) { T = malloc(sizeof(struct TreeNode)); if (T == NULL) { FatalError("out of space!!!"); } else { T->Element = X; T->Left = T->Right = NULL; } } else if (X < T->Element) T->Left = Insert(X, T->Left); else if (X > T->Element) T->Right = Insert(X, T->Right); return T; }
/*
1. 若x小于根节点的数据域的值,则删除左子树中X的值,否则
2. 若x大于根节点的数据域的值,则删除右子树的x的值,否则
3. 若根具有左子树和右子树,则删去根节点,从右子树的最小值作为新的根节点,并删去右子树的最小值,或者从左子树的最大值最为新的根节点,并删去左子树的最大值,否则
4. 若根只有一个子树,则删去根节点,将子树返回,否则
5. 该节点为叶子节点,直接删除
*/ SearchTree Delete(ElementType X, SearchTree T) { Position TmpCell; if (T == NULL) { Error("Element not found"); } else if (X < T->Element) T->Left = Delete(X, T->Left); else if (X>T->Right) T->Right = Delete(X, T->Right); else { if (T->Left && T->Right) { TmpCell = FindMin(T->Right); T->Element = TmpCell->Element; T->Right = Delete(T->Element, T->Right); } else { TmpCell = T; if (T->Left == NULL) { T = T->Right; } else if (T->Right == NULL) { T = T->Left; } free(TmpCell); } } return T; } void Preorder(SearchTree T) { if (T == NULL) { Error("Tree not found"); } if (T->Left != NULL) { Preorder(T->Left); } if (T->Right != NULL) { Preorder(T->Right); } printf("%d ", Retrieve(T)); }
4.testsearchtree.c
#include "fatal.h" #include "searchtree.h" #include <stdio.h> #include <stdlib.h> void main1() { SearchTree T = NULL; T = MakeEmpty(T); int i = 0; for (i = 0; i < 10;i++) { T= Insert(i, T); } Preorder(T); for (i = 0; i < 10; i++) { T = Delete(i, T); } system("pause"); } main() { SearchTree T; Position P; int i; int j = 0; T = MakeEmpty(NULL); for (i = 0; i < 50; i++) T = Insert(i, T); //for (i = 0; i < 50; i++, j = (j + 7) % 50) // T = Insert(j, T); Preorder(T); for (i = 0; i < 50; i++) if ((P = Find(i, T)) == NULL /*|| Retrieve(P) != i*/) printf("Error at %d ", i); for (i = 0; i < 50; i ++) T = Delete(i, T); //for (i = 1; i < 50; i += 2) // if ((P = Find(i, T)) == NULL || Retrieve(P) != i) // printf("Error at %d ", i); //for (i = 0; i < 50; i += 2) // if ((P = Find(i, T)) != NULL) // /*printf("Error at %d ", i);*/ printf("Min is %d, Max is %d ", Retrieve(FindMin(T)), Retrieve(FindMax(T))); system("pause"); return 0; }
3. 平衡二叉树
1.定义
一棵AVL树是其每个节点的左子树和右左子树的高度最多差1的二叉查找树。
节点的平衡因子BF=左子树深度-右子树深度。
树的深度保持为O(logN)。
2.平衡二叉树的实现
1. avl.h
#include <stdio.h> typedef int ElementType; #ifndef _AvlTree_H struct AvlNode; typedef struct AvlNode *Position; typedef struct AvlNode *AvlTree; AvlTree MakeEmpty(AvlTree T); Position Find(ElementType X, AvlTree T); Position FindMin(AvlTree T); Position FindMax(AvlTree T); AvlTree Insert(ElementType X, AvlTree T); AvlTree Delete(ElementType X, AvlTree T); ElementType Retrieve(Position P); #endif
2.avl.c
#include "avl.h" #include "fatal.h" #include <stdio.h> struct AvlNode { ElementType Element; AvlTree Left; AvlTree Right; int Height; }; AvlTree MakeEmpty(AvlTree T) { if (T != NULL) { MakeEmpty(T->Left); MakeEmpty(T->Right); free(T); } return NULL; } Position Find(ElementType X, AvlTree T) { if (T == NULL) { return NULL; } if (X < T->Element) { return Find(X, T->Left); } if (X>T->Element) { return Find(X, T->Right); } return T; } Position FindMin(AvlTree T) { if (T == NULL) { return NULL; } if (T->Left == NULL) { return T; } return FindMin(T->Left); } Position FindMax(AvlTree T) { if (T!= NULL) { while (T->Right != NULL) { T = T->Right; } } return T; } static int Height(Position P) { if (P == NULL) { return -1; } else { return P->Height; } } static Position SingleRoateWithLeft(Position K2) { Position K1; K1 = K2->Left; K2->Left = K1->Right; K2->Height = max(Height(K2->Left), Height(K2->Right)) + 1; K1->Height = max(Height(K1->Left), K2->Height) + 1; return K1; } static Position SingleRoateWithRight(Position K1) { Position K2; K2 = K1->Right; K1->Right = K2->Left; K2->Left = K1; K1->Height = max(Height(K1->Left), Height(K1->Right)) + 1; K2->Height = max(K1->Height, Height(K2->Right)) + 1; return K2; } static Position DoubleRoateWithLeft(Position K3) { K3->Left = SingleRoateWithRight(K3->Left); return SingleRoateWithLeft(K3); } static Position DoubleRoateWithRight(Position K1) { K1->Right = SingleRoateWithLeft(K1->Right); return SingleRoateWithRight(K1); } AvlTree Insert(ElementType X, AvlTree T) { //空树 if (T== NULL) { T = malloc(sizeof(struct AvlNode)); if (T == NULL) { FatalError("out of space!!!"); } else { T->Element = X; T->Height = 0; T->Left = T->Right = NULL; } } //X小于根节点的数据 else if (X < T->Element) { T->Left = Insert(X, T->Left); if (Height(T->Left) - Height(T->Right) == 2) { if (X < T->Left->Element) { T = SingleRoateWithLeft(T); } else T = DoubleRoateWithLeft(T); } } //X大于根节点数据 else if (X > T->Element) { T->Right = Insert(X, T->Right); if (Height(T->Right)- Height(T->Left) == 2) { if (X > T->Right->Element) { T = SingleRoateWithRight(T); } else { T = DoubleRoateWithRight(T); } } } //X等于根节点的数据,什么也不用做 T->Height = max(Height(T->Left), Height(T->Right)) + 1; return T; } ElementType Retrieve(Position P) { return P->Element; } AvlTree Delete(ElementType X, AvlTree T) { } void Inorder(AvlTree T) { if (T == NULL) { Error("Empty Tree "); } if (T ->Left != NULL) { Inorder(T->Left); } printf("%d ", T->Element); if (T->Right) { Inorder(T->Right); } printf(" "); }
3.testavl.c
#include "avl.h" #include "fatal.h" #include <stdio.h> #include <stdlib.h> void main() { AvlTree T = NULL; T = MakeEmpty(T); for (int i = 0; i < 10; i++) { T = Insert(i, T); } Inorder(T); printf("Max = %d ", Retrieve(FindMax(T))); printf("Min = %d ", Retrieve(FindMin(T))); for (int i = 0; i < 10; i++) { if (Find(i,T) == NULL) { FatalError("Find error "); } } system("pause"); }
4. 参考资源
http://blog.csdn.net/hguisu/article/details/7686515
http://blog.csdn.net/zealot_2002/article/details/8244436