经典查找算法一览无余(C++)

全文重点在代码–少理论

静态查找:只做查找操作,而不改动表中数据元素;

顺序查找

从表中的最后一个数据元素开始,逐个同记录的关键字做比较,如果匹配成功,则查找成功;反之,如果直到表中第一个关键字查找完也没有成功匹配,则查找失败。

//顺序查找--O(n)--遍历数组\链表
int test_sequential_search(int a[], int n, int keyval)
{
   
    for (int i = 0; i < n; i++)
    {
   
        if (a[i] == keyval)
            return i;  //返回下标
    }
    return -1;
}

二分查找(折半)-数组必有序

双指针查找某一个值是否存在(另一个作用:当查找元素重复时查找左右边界)

//二分查找--O(log2n)--双指针(找中点-mid)
int test_binary_search(int a[], int n,int keyval)
{
   
    if (n < 0 ) return -1;
    //定义双指针
    int left = 0;
    int right = n - 1; //用的下标
    int mid = ((right - left) >> 1 )+ left;
    while (left <=right)
    {
   
        if (keyval == a[mid])
        {
   
            return mid;
        }
        else if (a[mid] < keyval)
        {
   
            left = mid + 1;
        }
        else if (a[mid] > keyval)
        {
   
            right = mid - 1;
        }
    }
}

找边界

int left_bound(int[] nums, int target) {
   
    if (nums.length == 0) return -1;
    int left = 0;
    int right = nums.length; // 注意

    while (left < right) {
    // 注意
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
   
            right = mid;
        } else if (nums[mid] < target) {
   
            left = mid + 1;
        } else if (nums[mid] > target) {
   
            right = mid; // 注意
        }
    }
    return left;
}

动态查找:查找成功可以对其进行删除;如果查找失败,即表中无该关键字,可以将该关键字插入到表中。

二叉查找树(BST)

创建、查找、插入、删除
在这里插入图片描述
如果二叉排序树是平衡的,则n个节点的二叉排序树的高度为Log 2n+1,其查找效率为O(Log 2n),近似于折半查找。如果二叉排序树完全不平衡,(不平衡指右两边的子节点的数量不一致)则其深度可达到n,查找效率为O(n),退化为顺序查找。一般的,二叉排序树的查找性能在O(Log 2n)到O(n)之间。因此,为了获得较好的查找性能,就要构造一棵平衡的二叉排序树。很多改进版的二叉排序树可以使树高为O(logn),如AVL、红黑树等。对于排序二叉树,若按中序遍历就可以得到由小到大的有序序列。

**//二叉查找(排序、搜索)树-动态过程--[O(log2n),(n)]之间--创建、插入、删除、查找
/*
*二叉排序树中,如果其根结点有左子树,那么左子树上所有结点的值都小于根结点的值;
*二叉排序树中,如果其根结点有右子树,那么右子树上所有结点的值都大小根结点的值;
*二叉排序树的左右子树也要求都是二叉排序树;
*/

typedef struct BinarySearchTree
{
   
    int data;
    struct BinarySearchTree* left_child, * right_child;
}binary_search_tree;

//插入(创建)
void bst_insert(binary_search_tree*& p,int data)//改变指针的值需要二级指针
{
   
    if (p == NULL)//插入节点为空
    {
   
        if((p = new binary_search_tree)==NULL)
            cout<<"error"<<endl;
        p->data = data;
        p->left_child = p->right_child = NULL;
        
    }
  
    else if (p->data >= data) //根据二叉搜索树的特点左孩子比父节点小,右孩子比父节点大插入
            bst_insert(*(&(p->left_child)), data);//先取地址再取值
    else if (p->data < data)
            bst_insert(*(&(p->right_child)), data);
}
//查找
binary_search_tree* bst_search(binary_search_tree* p, int keyval)
{
   

    if (p == NULL)     
        return NULL;
    if (p->data == keyval)
        return p;
    else if (p->data > keyval)
        bst_search(*(&(p->left_child)), keyval);
    else if (p->data < keyval)
        bst_search(*(&(p->right_child)), keyval);
}
void delete_bst(binary_search_tree*& p, int del_val)//同理修改值针的地址
{
   
    if (p == NULL)
        return;
    else if(p->data==del_val)
    {
   
        if (p->left_child == NULL)//左孩子为空
        {
   
            binary_search_tree* temp = p;
            p = p->right_child;
            delete temp;
        }
        else//左孩子不为空时
        {
   
            binary_search_tree* head = p, *next = p->left_child;
            //找左子树的右子叶子节点,如果没有就父节点代替节点p,(为保持其它元素之间的相对位置不变,
            //可按中序遍历保持有序进行调整。比较好的做法是,找到*p的直接前驱(或直接后继)*next,
            //用*next来替换结点*p,然后再删除结点*next)
            while (next->right_child)                    //  eg1:        7      |  eg2:      7
            {
                                               //           2     8   |         2     8
                head = next;                             //        1  (null)    |       1   4
                next = next->right_child;                //                     |          3(null)
            }
            p->data = next->data;   //用*next来替换结点*p, eg2: head->data=2;next->data=4
            if (p = head)           //eg1所示:用2替代7,然后删除2;(即*next没有右叶子节点)
                p->left_child = next->left_child;
            else                    //eg2所示:用4替代7,然后删除4;(即*next有右叶子节点)
            {
   
                head->right_child = next->left_child;
            }
            delete next;//删掉直接前驱
        }
    }
    else if (p->data > del_val)
        delete_bst(*(&(p->left_child)), del_val);
    else if (p->data < del_val)
        delete_bst(*(&(p->right_child)), del_val);

}
//中序遍历输出
void printbst(binary_search_tree* p)
{
   
    if (p)
    {
   
        printbst( p->left_child);
        cout << p->data << ' ';
        printbst( p->right_child);
    }
}

//程序入口
void test_bstsearch(int a[],int n)
{
   
    //插入入口
    binary_search_tree* head=NULL;
    for (int i = 0; i < n; i++)
    {
   
        bst_insert(head, a[i]);
    }
    printbst(head);
    cout << endl;

    //查找入口
   /* binary_search_tree* temp = bst_search(head, 23);
    if(temp!=NULL)
    cout << "Find results:"<<temp->data << endl;
    else
    cout << "Not find. " << endl;*/

    //删除入口
    delete_bst(head, 7);
    printbst(head);
    cout << endl;
}**

平衡二叉树(VAL)

AVL有BST的所有性质,(比如中序遍历单调递增),但AVL是在BST的基础上优化而来,平衡化的结果,平衡因子<=1;

//平衡二叉树(AVL)--O(logn)--就是在二叉排序树(BST)的基础上,任意节点的左右子结点个数差不超过1;
//所以:每一次插入或者删除元素后都要判断是否平衡(不平衡就要旋转)

typedef struct AVL_tree {
   
    int data;
    struct AVL_tree* leftchild, *rightchild;
    int hight; //记录每个节点的深度
}avl_node,* avl_tree_t
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值