1.二叉查找树又称为二叉搜索树。二叉查找树和普通的二叉树在结构上一样,它要么是一棵空树,要么是这样的一棵二叉树:对任意结点,如果左子树不为空,则左子树上所有结点的权值都小于该结点的权值;如果右子树不为空,则右子树上所有结点的权值都大于该结点的权值;任意结点的左子树和右子树都是一棵二叉查找树;一般而言, 二叉查找树上结点的权值都是唯一的。
- 在二叉排序树上,对于任意结点,如果有左子树和右子树,那么其左子树上结点的权值都小于右子树上结点的权值。
- 如果中序遍历二叉排序树,会得到一个从小到大的序列。
- 二叉排序树的插入和查找效率相对较高,最坏情况下时间复杂度为 O(n),期望的时间复杂度为 O(logn),其中 n 为树上结点总个数。
刚才我们提到了二叉排序树最坏情况下时间复杂度为 O(n),这是为什么呢?最坏情况下,二叉排序树会退化成链表,从根结点往左依次递减,或者从根结点往右依次递增。那有什么方法可以解决这个问题呢?在二叉排序树的基础上可以加些优化,可以让其成为 AVL 树,红黑树,SBT,Splay 等等,这些高级的树结构解决了上面的问题,插入和查找的效率均为 O(logn)。
2.二叉排序树的性质
1 #include<iostream> 2 using namespace std; 3 class Node { 4 public: 5 int data; 6 Node *lchild, *rchild, *father; 7 Node(int _data, Node *_father = NULL) { 8 data = _data; 9 lchild = NULL; 10 rchild = NULL; 11 father = _father; 12 } 13 ~Node() { 14 if (lchild != NULL) { 15 delete lchild; 16 } 17 if (rchild != NULL) { 18 delete rchild; 19 } 20 } 21 void insert(int value) { //二叉查找树的插入(递归) 22 if (value == data) { 23 return; 24 } else if (value > data) { 25 if (rchild == NULL) { 26 rchild = new Node(value, this); 27 } else { 28 rchild->insert(value); 29 } 30 } else { 31 if (lchild == NULL) { 32 lchild = new Node(value, this); 33 } else { 34 lchild->insert(value); 35 } 36 } 37 } 38 Node* search(int value) { //二叉查找树的查找(递归) 39 if (data == value) { 40 return this; 41 } else if (value > data) { 42 if (rchild == NULL) { 43 return NULL; 44 } else { 45 return rchild->search(value); 46 } 47 } else { 48 if (lchild == NULL) { 49 return NULL; 50 } else { 51 return lchild->search(value); 52 } 53 } 54 } 55 Node* predecessor() { //找节点的前驱(左孩子节点孩子不为空) 56 Node *temp = lchild; 57 while (temp != NULL && temp->rchild != NULL) { 58 temp = temp->rchild; 59 } 60 return temp; 61 } 62 Node* successor() { //找节点的后继(右孩子节点不为空) 63 Node *temp = rchild; 64 while (temp != NULL && temp->lchild != NULL) { 65 temp = temp->lchild; 66 } 67 return temp; 68 } 69 void remove_node(Node *delete_node) { //删除度为1或0的节点 70 Node *temp = NULL; 71 if (delete_node->lchild != NULL) { 72 temp = delete_node->lchild; 73 temp->father = delete_node->father; 74 delete_node->lchild = NULL; 75 } 76 if (delete_node->rchild != NULL) { 77 temp = delete_node->rchild; 78 temp->father = delete_node->father; 79 delete_node->rchild = NULL; 80 } 81 if (delete_node->father->lchild == delete_node) { 82 delete_node->father->lchild = temp; 83 } else { 84 delete_node->father->rchild = temp; 85 } 86 delete delete_node; 87 } 88 bool delete_tree(int value){ //二叉查找树的删除 89 Node *delete_node,*current_node; 90 current_node=search(value); 91 if(current_node==NULL){ 92 return false; 93 } 94 if(current_node->lchild!=NULL){ 95 delete_node=current_node->predecessor(); 96 } 97 else if(current_node->rchild!=NULL){ 98 delete_node=current_node->successor(); 99 } 100 else{ 101 delete_node=current_node; 102 } 103 current_node->data=delete_node->data;//先替换,再转化为度为0的情况 104 remove_node(delete_node); 105 return true; 106 } 107 }; 108 class BinaryTree { 109 private: 110 Node *root; 111 public: 112 BinaryTree() { 113 root = NULL; 114 } 115 ~BinaryTree() { 116 if (root != NULL) { 117 delete root; 118 } 119 } 120 void insert(int value) { 121 if (root == NULL) { 122 root = new Node(value); 123 } else { 124 root->insert(value); 125 } 126 } 127 bool find(int value) { 128 if (root->search(value) == NULL) { 129 return false; 130 } else { 131 return true; 132 } 133 } 134 bool delete_tree(int value){ 135 return root->delete_tree(value); 136 } 137 }; 138 int main() { 139 BinaryTree binarytree; 140 int arr[10] = { 8, 9, 10, 3, 2, 1, 6, 4, 7, 5 }; 141 for (int i = 0; i < 10; i++) { 142 binarytree.insert(arr[i]); 143 } 144 int value; 145 cin >> value; 146 if (binarytree.find(value)) { 147 cout << "search success!" << endl; 148 } else { 149 cout << "search failed!" << endl; 150 } 151 cin>>value; 152 if(binarytree.delete_tree(value)){ 153 cout<<"delete success!"<<endl; 154 } 155 else{ 156 cout<<"delete failed!"<<endl; 157 } 158 return 0; 159 }