有序顺序表顺序搜索判定树:
扩充二叉树(用于分析的判定树):
其中第i个内部节点刚好处于第i-1个外部节点和i+1个内部节点之间
#include<iostream>
#include<queue>
using namespace std;
//设置为左闭右开
//二分查找非递归
int BinarySearch(int a[], int low, int high, int x) {
while (low < high) {//左闭右开取等的时候越界
int mid = (low + high) / 2;
if (x < a[mid])
high = mid;//high是不能取到的 所以不是mid-1
else if (a[mid] < x)
low = mid + 1;
else
return mid;
}
return -1;
}
//设置为左闭右开
//二分查找递归
int ReverseBinarySearch(int a[], int low, int high, int x) {
if (low < high) {//同样要满足这个条件
int mid = (low + high) / 2;
if (a[mid] == x)
return mid;
else if (a[mid] < x) {
return ReverseBinarySearch(a, mid + 1, high, x);//层层return需要return回去
}
else
return ReverseBinarySearch(a, low, mid, x);
}
return -1;//不满足返回-1
}
struct tree {
int val;
tree* lchild;
tree* rchild;
};
class BinarySearchTree {
public:
BinarySearchTree() {
root = NULL;
}
~BinarySearchTree() {
//层次遍历
//queue<tree*>q;
//if (root) {
// q.push(root);
// while (!q.empty()) {
// root = q.front(); q.pop();
// if (root->lchild)
// q.push(root->lchild);
// if (root->rchild)
// q.push(root->rchild);
// delete root;
// }
//}
//后序遍历
// 如果不用后序遍历,那么则需要将当前的根节点缓存,否则delete掉之后,找不到他的左右节点了
free(root);
}
void free(tree* root) {
if (root) {
free(root->lchild);
free(root->rchild);
delete root;
}
}
tree* create(int a[], int length) {//对一个数组建立二叉搜索树
for (int i = 0; i < length; ++i) {
Insert(root, a[i]);
}
return root;
}
//递归
bool RecursionInsert(tree*& root, int x) {//加了引用之后导致函数里的任何更改都可以导致root的变化
if (root == NULL) {
root = new tree;
root->val = x;
root->lchild = root->rchild = NULL;//一定要赋值为NULL啊 我晕
return true;
}
else if (x < root->val)
return RecursionInsert(root->lchild, x);
else if (root->val < x)
return RecursionInsert(root->rchild, x);
else
return false;//在二叉搜索树里面就有
}
bool Insert(tree*& root, int x) {//记得引用
//非递归不像递归,递归最后return回去的是最开始的根节点root.所以递归要用head来保存最开始的节点,像单链表一样
tree* p = root, * head = root;
if (!root) {
root = new tree();//每次new了,接受的是新的地址
head = root;//所以如果没有这句话,那么会导致head保存的是原来的root的地址,而不是新的
root->val = x;
root->lchild = root->rchild = NULL;
root = head;
return 1;
}
else {
while (root) {
if (x < root->val) {
p = root, root = root->lchild;//这种情况可以记录前驱节点
}
else if (root->val < x) {
p = root, root = root->rchild;
}
else {
root = head;//只要一返回就应该把root置为原来那个
return 0;
}
}
if (x < p->val) {
p->lchild = new tree();//因为本来为NULL,所以新赋值一个地址
p->lchild->val = x;
p->lchild->lchild = p->lchild->rchild = NULL;
}
else {
p->rchild = new tree();
p->rchild->val = x;
p->rchild->lchild = p->rchild->rchild = NULL;
}
root = head;
return 1;
}
}
//递归
tree* RecursionSearch(int x, tree* root) {
if (root == NULL)
return NULL;
else if (x < root->val)
return RecursionSearch(x, root->rchild);//老是忘记+return!
else if (root->val < x)
return RecursionSearch(x, root->rchild);
else
return root;
}
tree* Search(int x, tree* root) {
while (root) {
if (x < root->val)
root = root->lchild;
else if (root->val < x)
root = root->rchild;
else
return root;
}
return NULL;
}
bool del(int x, tree*& root) {
tree* p, * q;
if (root) {
if (x < root->val)
return del(x, root->lchild);
else if (root->val < x)
return del(x, root->rchild);
else {
//当左右子树都不为空的时候,找到右子树的中序遍历第一个节点(本文算法)或者是左子树中序遍历最后一个节点
//右子树的中序遍历第一个节点就是右子树中最小的但又比原来根节点大的
if (root->lchild && root->rchild) {
p = root->rchild;
while (p->lchild)
p = p->lchild;
root->val = p->val;
return del(p->val, root->rchild);//然后删除这个中序遍历的第一个节点,即进入函数后进入这里所在的下一个else分支
}
//可以迭代,算法如下
/*
if (root->lchild && root->rchild) {
q=root;
p = root->rchild;
while (p->lchild)
q=p,p = p->lchild;
root->val = p->val;
if(q!=p)
q->lchild=p->rchild;
else
q->rchild=p->rchild;
delete p;
}
*/
else {
p = root;
if (!root->lchild)
root = root->rchild;//因为是引用 可以直接链接 把地址传过去
else
//可以合并到一块去
root = root->lchild;
delete p;
return true;
}
}
}
return false;
}
private:
tree* root;
};
int main() {
int b[] = { 0,1,2,3,4,5,6,7,8,9 };
cout << "BinarySearch " << BinarySearch(b, 0, 10, 0) << endl;
cout << "ReverseBinarySearch " << ReverseBinarySearch(b, 0, 10, 0) << endl;
cout << "BinarySearch " << BinarySearch(b, 0, 10, -1) << endl;
cout << "ReverseBinarySearch " << ReverseBinarySearch(b, 0, 10, -1) << endl;
cout << "BinarySearch " << BinarySearch(b, 0, 10, 9) << endl;
cout << "ReverseBinarySearch " << ReverseBinarySearch(b, 0, 10, 9) << endl;
cout << "BinarySearch " << BinarySearch(b, 0, 10, 5) << endl;
cout << "ReverseBinarySearch " << ReverseBinarySearch(b, 0, 10, 5) << endl;
BinarySearchTree BT; tree* root;
int a[] = { 6,3,5,2,1,4 };
root = BT.create(a, 6);
cout << " b.RecursionInsert(root, 1); " << BT.RecursionInsert(root, 1) << endl;
cout << " b.Insert(root, 8); " << BT.Insert(root, 8) << endl;
cout << "b.RecursionSearch(6,root); " << BT.RecursionSearch(6, root) << endl;
cout << "b.search(6,root); " << BT.Search(6, root) << endl;
cout << "b.del(5, root); " << BT.del(5, root) << endl;
return 0;//不写这个会导致不进行析构函数,我之前的所有的delete真是delete个寂寞。无语。
}