二叉搜索树的简介:
二叉搜索树通常采取二叉链作为二叉搜索树的存储结构。中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)),在最坏的情况下,二叉搜索树会退化为一个链表。为了解决这个问题呢,人们又提出了平衡搜索树;
二叉搜索树的性质:
1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。
2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。
3. 右子树上所有节点的关键码(key)都大于根节点的关键码(key)。
4. 左右子树都是二叉搜索树。
如图:
/*节点结构*/
template<class K> struct Node { public: Node(K Key) :key(Key),Left(NULL), Right(NULL) {} K key; Node<K>* Left; Node<K>* Right; };
/*平衡搜索树类*/
template<class K> class SearchBinaryTree { public: SearchBinaryTree(K* key,size_t size) :_root(NULL) { for (int i = 0; i < size; ++i) //Creat(_root, key[i]); Creat_Nor(_root,key[i]); } bool Creat(Node<K>*& root, K key); //递归创建 bool Creat_Nor(Node<K>*& root, K key); //非递归创建 bool Delete(Node<K>* root, K key); //删除某一节点 Node<K>* Find(Node<K>* root, K key); //查找某一节点 Node<K>* Find_Nor(Node<K>* root, K key); //非递归查找某一节点 void InOrder(Node<K>* root); //中序遍历 public: Node<K>* _root; };
/*相关函数的实现*/
template<class K> bool SearchBinaryTree<K>::Creat(Node<K>*& root,K key) { if (root == NULL) { root = new Node<K>(key); return true; } if (key > root->key) return Creat(root->Right, key); else if (key < root->key) return Creat(root->Left, key); else return false; }
template<class K> bool SearchBinaryTree<K>::Creat_Nor(Node<K>*& root, K key) { if (root == NULL) { root = new Node<int>(key); return true; } Node<K>* prev = NULL; Node<K>* cur = root; while (cur) { prev = cur; if (key > cur->key) { cur = cur->Right; } else if (key < cur->key) { cur = cur->Left; } else return false; } if (prev->key < key) { prev->Right = new Node<K>(key); } else { prev->Left = new Node<K>(key); } return true; }
template<class K> bool SearchBinaryTree<K>::Delete(Node<K>* root, K key) { if (root == NULL) { return false; } Node<K>* prev = NULL; while (root) { if (key > root->key) { prev = root; root = root->Right; } else if (key < root->key) { prev = root; root = root->Left; } else //找的了相应的节点需要删除了 { if (root->Left == NULL) //左为空 { if (prev == NULL) { _root = root->Right; } else if (root->key > prev->key) { prev->Right = root->Right; } else { prev->Left = root->Right; } delete root; } else if (root->Right == NULL) //右为空 { if (prev == NULL) { _root = root->Left; } else if (root->key > prev->key) { prev->Right = root->Left; } else { prev->Left = root->Left; } } else //两边都不为空 { if (prev == NULL) { _root = root; } Node<K>* tmp = root->Right; prev = root; //root 的右子树的最左节点就是 root->right,保证prev始终是tmp的父亲节点 while (tmp->Left) { prev = tmp; tmp = tmp->Left; } swap(tmp->key, root->key); prev == root ? prev->Right = tmp->Right : prev->Left = tmp->Right; } return true; } } return false; }
当左孩子,右孩子都不为空时,为什么要将右子树的最左孩子与root交换呢,原因是:交换之后能够保证 root->left->key < root->key && root->right->key > root->key
从而使得这个搜索二叉树依然有序
template<class K> Node<K>* SearchBinaryTree<K>::Find(Node<K>* root, K key) { if (root == NULL) { return NULL; } if (key > root->key) { return Find(root->Right, key); } else if (key < root->key) { return Find(root->Left, key); } else { return root; } } template<class K> Node<K>* SearchBinaryTree<K>::Find_Nor(Node<K>* root, K key) { if (root == NULL) { return NULL; } while (root) { if (key > root->key) root = root->Right; else if (key < root->key) root = root->Left; else return root; } return NULL; } template<class K> void SearchBinaryTree<K>::InOrder(Node<K>* root) { if (root == NULL) { return; } InOrder(root->Left); cout << root->key << " "; InOrder(root->Right); }
二叉搜索树,就到这里了,欢迎参与评论,请不吝赐教~~
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html