第八章 查找

查找基本概念

平均查找长度ASL(Average Search Length)

查找失败

顺序查找
// 顺序查找顺序表
int search(int arr[] , int n , int key){
    int i;
    for(i = 0 ; i < n ; ++i){
        if(arr[i] == key)
            return i;
    }
    return -1;		// 未查找到对应元素
}

// 顺序查找链表
LNode *search(LNode *head , int key){
    LNode *p = head->next;
    while(p != NULL){
        if(p->data == key)
            return p;
        p = p->next;
    }
    return NULL;
}
折半查找

也称为二分查找,适用于有序序列的查找。

// 折半查找
int Bsearch(int arr[] , int low , int high , int key){
    while(low <= high){
        int mid = (low + high) / 2;
        if(arr[mid] == key){
            return mid;
        }
        else if(arr[mid] > key){
            high = mid - 1;
        }
        else{
            low = mid + 1;
        }
    }
    return -1;		// 未查找到对应元素
}
二叉排序树(重点)

排序二叉树:左子树小于根节点;右子树大于根节点

查找元素:

<1>p先指向根节点;

<2>若根节点值大于目标元素,则向左走

<3>若根节点值小于目标元素,则向右走

<4>重复上述步骤;

<5>当走到空指针处时,还未找到目标元素,则表示未找到。

// 二叉排序树
// 向左走为大,向右走为小
BTNode *BSTsearch(BTNode *p , int key){
    while(p != NULL){
        if(key == p->key)
            return p;
        else if(key < p->key)
            p = p->lchild;
        else
            p = p->rchild;
    }
    return NULL;		// 未查找到对应元素
}
// 二叉排序树插入算法
// 对一个不存在二叉排序树的关键字,其查找不成功的位置就是关键字的对应插入位置
int insert(BTNode *&bt , int key){
    if(bt == NULL){
        bt = new BTNode;
        bt->lchild = NULL;
        bt->rchild = NULL;
        bt->key = key;
        return 1;				// 成功插入返回1
    }
    else{
        if(key == bt->key)
            return 0;			// 二叉排序树中已经存在对应关键字,则插入失败
    }
    else if(bt->key > key)
        return insert(bt->lchild , key);	// 进入左子树递归
    else
        return insert(bt->rchild , key);	// 进入右子树递归
}

建树:从一棵空树开始,不断的插入元素即可。

删除结点:

<1>叶子结点则直接删除即可;

<2>根节点(既有左也有右):要么向左走一步,然后向右走到底,最底下的元素与根节点交换后删除;或者向右走一步,然后向左走到底,最底下的元素与根节点交换后删除;

<3>只有右孩子:删除后将右孩子接上;

<4>只有左孩子:删除后将左孩子接上。

平衡二叉树(重点)

相当于二叉排序树的升级版

二叉排序树如果越矮,则越能减少平均查找时间长度。

平衡因子:对应结点左子树的高度减去其右子树高度的差。

平衡二叉树:其各个节点的平衡因子的绝对值不大于1

平衡调整:

<1>LL调整:右单旋转调整

<2>RR调整:左单旋转调整

<3>RL调整:先右后左双旋转调整

<4>LR调整:先左后右双旋转调整

散列表(重点)

根据关键字的值来计算关键字在散列表中的位置

例题:假设关键字序列为{7,4,1,14,100,30,5,9,20,134},且哈希函数为:H(key) = key mod 13。求表长为12的哈希表。

常见的哈希函数:

<1>直接定址:取关键字或关键字的某个线性函数为哈希地址,比如H(key) = a * key + b【a,b为常数】

<2>数字分析:选取不容易发生哈希冲突的数字位数,比如电话号码的后四位

<3>平方取中:取关键字的平方后的中间即为作为哈希地址。【适用于位数较少的数据】

<4>除留余数:取关键字被某个不大于哈希表长的数字p除后所得的余数为哈希地址,比如H(key) = key mod p【p小于等于哈希表长】

常见处理哈希冲突的方法:

<1>开放定址法:线性探查法

H(key) = (H(key) + i) mod len【其中,i小于len,len是哈希表长】

特点:可以探查表中的所有位置,但是容易发生堆积问题。

<2>平方探查法:假如发生冲突的位置是d,则探测的新地址是:

d + 1² d - 1² d + 2² d - 2² …

特点:不可以探查到表中的所有位置(至少可以探查一半位置),但是不容易产生堆积问题。

<3>链地址法:也称为拉链法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值