特点
非空左子树的所有结点的值小于其根结点的值。
非空右子树的所有结点的值大于其根结点的值。
左、右子树都是二叉搜索树。
实现
主要操作
查询:
实现思路:
递归:调用递归方法,传入要查询的树的根节点和要查询的值,判断根节点值大小,然后递归查询。
非递归:通过while循环,判断当前指针指向的节点值是否满足条件或者当前指针是否为空。然后根据情况令指针指向当前节点的左子节点或者右子节点。如果当前节点变为空,说明没有找到目标值。
插入:
递归:调用递归方法,传入要插入的值和树的根节点。如果当前根节点值小于插入的值,递归调用插入方法,传入右子树的根节点。如果当前根节点值大于插入的值,递归调用插入方法,传入左子树的根节点。如果相等,报错(二叉搜索树不允许存在重复的值) 。
非递归:通过while循环,通过判断插入值的大小,不断改变遍历的指针指向的节点,同时用另一个指针记录上一个遍历过的节点(方便查找到叶子节点时向前看一个节点,便于操作)。
删除:
首先找到要删除的节点,然后判断情况。主要分为三种情况:
左子树为空,只有右子树:直接将右子树向上提升一级(用右子树替换要删除的节点,然乎释放要删除的节点的空间(new
出来的当然要delete
))。
右子树为空,只有左子树:直接将左子树向上提升一级(思路同上)。
左右子树都不为空 :将右子树中值最小的节点和要删除的节点交换,然后删除目标节点(此时目标节点已经在原右子树最小元素的位置上,但该位置可能是一个分叉节点,所以应该递归调用删除方法进行删除)。
C++实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 #include <iostream> #include <queue> struct Node { int data; Node *left; Node *right; Node (int data) { this ->data = data; left = nullptr ; right = nullptr ; } Node (int data, Node *left, Node *right) { this ->data = data; this ->left = left; this ->right = right; } }; class BST {private : Node *root; public : BST () { root = nullptr ; } BST (int root_data) { root = new Node (root_data); } Node *get_root () { return root; } void insert_recursion (int data) { if (root == nullptr ) { root = new Node (data); return ; } recursion_insert (root, data); } void insert_unrecursion (int data) { if (root == nullptr ) { root = new Node (data); return ; } Node *current = root; Node *parent; while (current != nullptr ) { parent = current; if (current->data > data) { current = current->left; } else if (current->data < data) { current = current->right; } else { std::cout << "insert error: data is already exist" << std::endl; return ; } } if (parent->data > data) { parent->left = new Node (data); } else { parent->right = new Node (data); } } Node *search (int data) { if (root == nullptr ) { return nullptr ; } Node *parent = nullptr ; Node *current = root; while (current != nullptr ) { parent = current; if (current->data == data) { return current; } else if (current->data > data) { current = current->left; } else { current = current->right; } } return nullptr ; } void delete_node (int data) { if (root == nullptr ) { printf ("delete failed: tree has zero node" ); return ; } delNode (root, data); } ~BST () { destroyTree (root); } private : void recursion_insert (Node *&node, int data) { if (node == nullptr ) { node = new Node (data); return ; } if (data > node->data) { recursion_insert (node->right, data); } else if (data < node->data) { recursion_insert (node->left, data); } else { std::cout << "insert error: data is already exist" << std::endl; } } void delNode (Node *&root, int data) { if (root == nullptr ) { return ; } else if (root->data < data) { delNode (root->right, data); } else if (root->data > data) { delNode (root->left, data); } else { if (root->left == nullptr ) { Node *temp = root; root = root->right; printf ("deleted node: %d\n" , temp->data); delete temp; return ; } if (root->right == nullptr ) { Node *temp = root; root = root->left; printf ("deleted node: %d\n" , temp->data); delete temp; return ; } Node *current = root->right; while (current != nullptr && current->left != nullptr ) { current = current->left; } int temp = current->data; current->data = root->data; root->data = temp; delNode (root->right, current->data); } } void destroyTree (Node *root) { if (root == nullptr ) { return ; } if (root->left != nullptr ) { destroyTree (root->left); } if (root->right != nullptr ) { destroyTree (root->right); } std::cout << "destroyed node: " << root->data << std::endl; delete root; } }; void inorderPrintTree (Node *root) { if (root == nullptr ) { return ; } inorderPrintTree (root->left); std::cout << root->data << " " ; inorderPrintTree (root->right); } int main () { int arr[] = {5 , 3 , 2 , 4 , 7 , 6 , 8 }; int size = sizeof (arr) / sizeof (arr[0 ]); BST bst = BST (); for (int i = 0 ; i < size; ++i) { bst.insert_unrecursion (arr[i]); } inorderPrintTree (bst.get_root ()); printf ("\n" ); for (int i = 0 ; i < size; ++i) { if (bst.search (arr[i])) { printf ("find %d\n" , arr[i]); } else { printf ("not found %d\n" , arr[i]); } } for (int i = 0 ; i < size; ++i) { bst.delete_node (arr[i]); } return 0 ; }
正确输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2 3 4 5 6 7 8 find 5 find 3 find 2 find 4 find 7 find 6 find 8 deleted node: 5 deleted node: 3 deleted node: 2 deleted node: 4 deleted node: 7 deleted node: 6 deleted node: 8