查找基本概念
平均查找长度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>链地址法:也称为拉链法。