【数据结构】二分查找和二分搜索(排序)树总结

二分查找法:作用在有序的数列中

注意边界的关系

// 二分查找法,在有序数组arr中,查找target
// 如果找到target,返回相应的索引index
// 如果没有找到target,返回-1
template
int binarySearch(T arr[], int n, T target){

    // 在arr[l...r]之中查找target
    int l = 0, r = n-1;
    while( l <= r ){  //直到l大于r的时候这个边界才会消失 

        //int mid = (l + r)/2; 这个可能会出现越界问题    
        int mid = l + (r-l)/2;  //用最小的值加一个范围再除以2 
        if( arr[mid] == target )
            return mid;

        if( arr[mid] > target )
            r = mid - 1;
        else   
            l = mid + 1;
    }

    return -1;
}


// 用递归的方式写二分查找法
template
int __binarySearch2(T arr[], int l, int r, T target){

    if( l > r )
        return -1;

    int mid = (l+r)/2;
    if( arr[mid] == target )
        return mid;
    else if( arr[mid] > target )
        return __binarySearch2(arr, 0, mid-1, target);
    else
        return __binarySearch2(arr, mid+1, r, target);

}

二分搜索树:

从上表可以看出二分搜索树是很高效的,无论是查找还是插入还是删除,所以在维护程序的时候,用二分排序树是很有必要的!二分搜索树不一定是一棵完全二叉树,所以它不能用数组来,要用指针和结点来表示

template 
class BST{

private:
    struct Node{
        Key key;
        Value value;
        Node *left;
        Node *right;

        Node(Key key, Value value){
            this->key = key;
            this->value = value;
            this->left = this->right = NULL;
        }
    };

    Node *root;
    int count;
 public:
    BST(){
        root = NULL;
        count = 0;
    }
    ~BST(){
        // TODO: ~BST()
    }

    int size(){
        return count;
    }

    bool isEmpty(){
        return count == 0;
    }
};
    //用递归的方式插入一个结点
	// 向以node为根的二叉搜索树中,插入节点(key, value)
    // 返回插入新节点后的二叉搜索树的根
    Node* insert(Node *node, Key key, Value value){

        if( node == NULL ){
            count ++;
            return new Node(key, value);
        }

        if( key == node->key )
            node->value = value;
        else if( key < node->key )
            node->left = insert( node->left , key, value);
        else    // key > node->key
            node->right = insert( node->right, key, value);

        return node;
    }

// 查看以node为根的二叉搜索树中是否包含键值为key的节点
    bool contain(Node* node, Key key){

        if( node == NULL )
            return false;

        if( key == node->key )
            return true;
        else if( key < node->key )
            return contain( node->left , key );
        else // key > node->key
            return contain( node->right , key );
    }
    // 在以node为根的二叉搜索树中查找key所对应的value
    Value* search(Node* node, Key key){  //用Value*是为了防止查找失败的时候返回一个空而使程序崩溃,而用指针则可以保存空值

        if( node == NULL )
            return NULL;

        if( key == node->key )
            return &(node->value);
        else if( key < node->key )
            return search( node->left , key );
        else // key > node->key
            return search( node->right, key );
    }
//递归的方法对树进行遍历
    // 对以node为根的二叉搜索树进行前序遍历
    void preOrder(Node* node){

        if( node != NULL ){
            cout<key<left);
            preOrder(node->right);
        }
    }

    // 对以node为根的二叉搜索树进行中序遍历
    void inOrder(Node* node){

        if( node != NULL ){
            inOrder(node->left);
            cout<key<right);
        }
    }

    // 对以node为根的二叉搜索树进行后序遍历
    void postOrder(Node* node){

        if( node != NULL ){
            postOrder(node->left);
            postOrder(node->right);
            cout<key<

层序遍历就是广度优先遍历(要用队列)

    // 层序遍历
    void levelOrder(){

        queue q;
        q.push(root);  //入队根结点
        while( !q.empty() ){

            Node *node = q.front();   //取出队首元素
            q.pop(); //出队

            cout<key<left )
                q.push( node->left );   //左孩子入队
            if( node->right )
                q.push( node->right );   //右孩子入队
        }
    }

删除

    // 在以node为根的二叉搜索树中,返回最小键值的节点
    Node* minimum(Node* node){
        if( node->left == NULL )
            return node;

        return minimum(node->left);
    }

    // 在以node为根的二叉搜索树中,返回最大键值的节点
    Node* maximum(Node* node){
        if( node->right == NULL )
            return node;

        return maximum(node->right);
    }

    // 删除掉以node为根的二分搜索树中的最小节点
    // 返回删除节点后新的二分搜索树的根
    Node* removeMin(Node* node){

        if( node->left == NULL ){

            Node* rightNode = node->right;
            delete node;
            count --;
            return rightNode;
        }

        node->left = removeMin(node->left);
        return node;
    }

    // 删除掉以node为根的二分搜索树中的最大节点
    // 返回删除节点后新的二分搜索树的根
    Node* removeMax(Node* node){

        if( node->right == NULL ){

            Node* leftNode = node->left;
            delete node;
            count --;
            return leftNode;
        }

        node->right = removeMax(node->right);
        return node;
    }

    // 寻找最小的键值
    Key minimum(){
        assert( count != 0 );
        Node* minNode = minimum( root );
        return minNode->key;
    }

    // 寻找最大的键值
    Key maximum(){
        assert( count != 0 );
        Node* maxNode = maximum(root);
        return maxNode->key;
    }

    // 从二叉树中删除最小值所在节点
    void removeMin(){
        if( root )
            root = removeMin( root );
    }

    // 从二叉树中删除最大值所在节点
    void removeMax(){
        if( root )
            root = removeMax( root );
    }

ximum(root);
return maxNode->key;
}

// 从二叉树中删除最小值所在节点
void removeMin(){
    if( root )
        root = removeMin( root );
}

// 从二叉树中删除最大值所在节点
void removeMax(){
    if( root )
        root = removeMax( root );
}



你可能感兴趣的:(数据结构)