二叉搜索树
二叉搜索树是一颗二叉树或一颗空树且满足以下性质:
1)根节点 x的key值大于任意左子树上节点的key值,小于右子树上任意节点的key值 ;
2)其左右子树也分别是一颗二叉搜索树。
/** * zhanw15 @2018/4/12 * * filename: tree.h * 二叉搜索树,红黑树定义 */ #include<stdlib.h> typedef struct binaryTree { int key; binaryTree *p; //parent binaryTree *left; //left_son binaryTree *right; //right_son }binaryTree;
/** * zhanw15 @2018/4/12 * 算法导论 12章 * * 二叉搜索树 @P286 * filename: binaryTree.cpp * * @Operation = { Search, Min, Max, Delete, Insert, PredecessOR, SuccessOR}; */ #include <stdio.h> #include "..\tree.h" /* 访问节点 */ void visit( binaryTree *a) { printf( "%d ", a->key); } /* 中序遍历 时间复杂度 n */ void Inorder_Tree( binaryTree *a) { if( a==NULL) return; Inorder_Tree( a->left); visit( a); Inorder_Tree( a->right); } /* 查找二叉搜索树 迭代版本*/ binaryTree *Tree_Search( binaryTree *a, int k) { while( a!=NULL && a->key!=k) { if( a->key<k) a = a->right; else a = a->left; } return a; } /* 获取二叉搜索树最大值节点 */ binaryTree *Tree_Min_Key( binaryTree *a) { if( a==NULL) return a; //if( a->right==NULL) return a; //return a->right; //滥用递归不是个好习惯 while( a->left!=NULL) a = a->left; return a; } /* 获取二叉搜索树的最小值节点 */ binaryTree *Tree_Max_Key( binaryTree *a) { if( a==NULL) return a; while( a->right!=NULL) a = a->right; return a; } // 在某一遍历次序下,得到最后的遍历结果,若x1、x2相邻, // 且x1在x2前,则称x1是x2的前驱,x2是x1的后继 /* 中序遍历下二叉搜索树的前驱 */ binaryTree *PredecessOR( binaryTree *a) { if( a->left!=NULL) return Tree_Max_Key( a->left); while( a->p!=NULL && a->p->left==a) { a = a->p; } return a->p; } /* 中序遍历下二叉搜索树的后继 */ binaryTree *SuccessOR( binaryTree *a) { if( a->right!=NULL) return Tree_Min_Key( a->right); while( a->p!=NULL && a->p->right==a) { a = a->p; } return a->p; } /* 插入节点 时间复杂度: h(树高度) */ binaryTree *Tree_Insert( binaryTree *Head, binaryTree *a) { if( a==NULL) return Head; //找到插入节点的位置 binaryTree *t = Head, *temp = Head; while( t!=NULL) { temp = t; if( t->key>a->key) t = t->left; else t = t->right; } //插入节点 if( temp==NULL) Head = a; else if( a->key > temp->key) { temp->right = a; } else { temp->left = a; } a->p = temp; return Head; } /* 将u位置子树替换为v子树 */ binaryTree *Transplant( binaryTree *Head, binaryTree *u, binaryTree *v) { if( u->p==NULL) Head = v; else { if( u==u->p->left) u->p->left = v; else u->p->right = v; } if( v!=NULL) v->p = u->p; return Head; } /* 删除节点 时间复杂度: h*/ binaryTree *Tree_Delete( binaryTree *Head, binaryTree *a) { if( a==NULL) return Head; //若节点左或右无子树,则拿右或左子树替换掉当前节点 if( a->left==NULL) Head = Transplant( Head, a, a->right); else if( a->right==NULL) Head = Transplant( Head, a, a->left); else { // 若左右子树均存在,则使用其后继替换此节点 binaryTree *y = Tree_Min_Key( a->right); /** * 若后继节点不是其右孩子,那么后继节点一定是其右子树的最小值,\ * 且其后继一定没有左子树(参看后继定义) */ if( y->p!=a) { Head = Transplant( Head, y, y->right); y->right = a->right; y->right->p = y; } Head = Transplant( Head, a, y); y->left = a->left; y->left->p = y; } free( a); return Head; } int main() { int a[17] = { 14, 32, 43, 4, 23, 7, 64, 13, \ 90, 70, 12, 24, 1, -4, 48, 22, 65}; binaryTree *Head=NULL; for( int i=0; i<17; i++) { //插入元素 binaryTree *temp = new binaryTree; (*temp) = { a[i], NULL, NULL, NULL}; Head = Tree_Insert( Head, temp); } Inorder_Tree( Head); int k = 7; //测试:查找、前驱、后继 printf( "\nkey = %d Suce: %d Pred: %d\n", k, SuccessOR\ ( Tree_Search( Head, k))->key, PredecessOR( Tree_Search( Head, k))->key); int k2 = 4; //测试: 删除值为4的节点 Inorder_Tree( Head = Tree_Delete( Head, Tree_Search( Head, k2))); return 0; } // output: (mingw gcc 4.7.2 32-bit) // -4 1 4 7 12 13 14 22 23 24 32 43 48 64 65 70 90 // key = 7 Suce: 12 Pred: 4 // -4 1 7 12 13 14 22 23 24 32 43 48 64 65 70 90
持续更新中。。。