c++常见的查找算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2).绕某元素左旋转(RR型调整)
80 90
/ \左旋/ \
60 90 ------> 80 120
/ \ / \ /
源自文库85 120 60 85 100
/
100
a) BST树b ) AVL树
注:当树中结点X的右孩子的右孩子上插入新元素,且平衡因子从-1变成-2后,就需要绕节点X进行左旋转。
3).绕某元素的左子节点左旋转,接着再绕该元素自己右旋转(LR)。
}
c.时间复杂度:O(n)
2).折半查找//又称二分查找
a.算法思想:
在有序表中,取中间元素作为比较对象,若给定元素与中间元素相等,则查找成功。
若给定元素小于中间元素,则在中间元素的左半区继续查找,若给定元素大于中间元素,则在中间元素右半区继续查找,不断重复上述查找过程。
b.算法实现:
int binarySearch(int array[], int n, int data)//查找序列必须有序
失衡状态可归纳为4种,它们对应着4种旋转类型:
1).绕某元素右旋转(LL型调整)
100 85
/ \右旋/ \
85 120 --------> 60 100
/ \ \ / \
60 90 80 90 120
\
80
a) BST树b) AVL树
注:当树中结点X的左孩子的左孩子上插入新元素,且平衡因子从1变成2后,就需要绕节点X进行右旋转。
查找:查找也称检索,是根据给定的某个值,在查找表中确定一个其关键字等于给定值的记录或数据元素。若表中存在一个这样的记录,则称查找成功,反之查找失败。
2.查找分类
2.1线查找
1).顺序查找
a.算法思想:
设查找表是由n(n>0)个元素组成的,从第一个元素开始,顺序查找给定元素,若找到查找成功,反之失败。
当结点的BF值由0变为1或-1时,表明原本等高左右子树由于一边变高而导致失衡,整棵子树的高度变高,所以必须向上修改祖先结点的BF值。
e. AVL树的查找:
AVL树的查找同二叉查找树的查找。
f.程序举例
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
}blockList;
//索引结点类型定义
typedef struct IndexNode {
int indexKey;//索引关键字域
int indexNum;//指向块的第一个元素的下标
}indexList;
//分块查找
int indexSearch(blockList b[], int m, indexList i[], int n, int key)
indexList index[I] = {{14, 0}, {34, 5}};
r = indexSearch(list, B, index, I, 6);
printf("待查元素所在位置下表:%d\n", r);
return 0;
}
2.2树型查找
1).二叉查找树查找(B树)
a.二叉查找树定义:
二叉排序树又称二叉查找树,它或者是一棵空树,或者是一棵具有如下性质的非空二叉树:
常见查找算方法总结
1.基本概念
数据:数据即信息的载体,是对客观事物的符号表示,指能输入到计算机中并被计算机程序处理的符号的总称。
数据项:数据项是数据具有独立意义的不可分割的最小单位,是对数据元素属性的描述。
数据元素:数据元素是数据的基本单位,是对一个客观实体的数据描述。
查找表:进行查找的数据元素通常是同一类型的数据元素或记录,由它们构成的集合称查找表。
{
int low, mid, high;
if(array == NULL) return -1;//查找失败
low = 0;
high = n - 1;
while(low <= high) {
mid = (low + high) / 2;
if(data == array[mid]) return mid; //查找成功
如果二叉查找树根结点关键字小于待查找关键字,则用同样的方法在根结点的右子树上查找。
如果二叉查找树根结点关键字大于待查找关键字,则用同样的方法在根结点的左子树上查找。
c.算法实现:
typedef int keytype;
//二叉查找树结点类型定义
typedef struct BSTNode {
keytype key;
lc->rchild = bbt;
bbt = lc;
}
//RR型调整
void leftRotate(bbtnode *bbt)
{
bbtnode *rc = NULL;
rc = bbt->rchild;//rc指向*bbt的右孩子
bbt->rchild = rc->lchild;
rc->lchild = bbt;
(1).若它的左子树非空,则左子树上的所有结点的关键字的值均小于根结点的值。
(2).若它的右子树非空,则右子树上的所有结点的关键字的值均大于(如果允许有相同的关键字的值的结点存在,则大于等于)根结点的值。
(3).左右子树本身又各是一棵二叉排序树。
b.算法思想:
当二叉查找树为空时,查找失败。
如果二叉查找树根结点关键字等于待查找关键字,则查找成功。
b.算法实现:
#include <stdio.h>
#include <stdlib.h>
#define B 10
#define I 2
typedef char datatype;
//块结点类型定义
typedef struct BlockNode {
int key;//关键字域
datatype data;//其它域
struct BSTNode *lchild, *rchild;
}bstNode;
//非递归查找
bstNode *bstSearch(bstNode *t, keytype k)
{
bstNode *p, *q;
int flag = 0;
p = t;
while(p && !flag) {
if(p->key == k) flag = 1;
它的左子树和右子树都是平衡二叉树。
同时左子树和右子树的深度(高度)之差的绝对值(平衡因子)不超过1。
b.平衡因子定义:
平衡因子(Balance Factor)定义为该节点的左子树的深度减去其右子树的深度,则平衡二叉树上所有节点的平衡因子只可能是-1、0和1。
只要树上有一个节点的平衡因子的绝对值大于1,则该二叉树就是不平衡的了。
else if(data < array[mid]) high = mid - 1;
else low = mid + 1;
}
return -1;//查找失败
}
c.时间复杂度:O(lgn)
3).分块查找//又称索引顺序查找,它是顺序查找的一种改进,是一种性能介于顺序查找和二分查找之间的查找方法。
a.算法思想:
else if(p->key > k) p = p->lchild;
else p = p->rchild;
}
if(flag) return p;
else return NULL;
}
d.时间复杂度:
最坏:O(n)
平均:O(lgn)
2).平衡二叉树查找
a.平衡二叉树定义:
平衡二叉树,又称AVL树。它除了具备二叉查找树的特征之外,还具有如下的特征:
else low = mid + 1;
}
if(low < n) {//二分查找完毕,low下标的索引项对应的块中可能存在待查找元素。
//确定块起始位置
start = i[low].indexNum;
//确定块终止位置
if(low == n - 1) {//若带查找元素在最后一个块中
end = m - 1;
注:当树中节点X的右孩子的左孩子上插入新元素,且平衡因子从-1变成-2后,就需要先绕X的右子节点Y右旋转,接着再绕X左旋转。
d. AVL树的插入:
只有根结点到插入结点路径(称为插入路径)上的结点的BF值会被改变。
当一个结点插入到某个结点的左子树时,该结点的BF值加1。
当一个结点插入到某个结点的右子树时,该结点的BF值减1。
#define FALSE 0
#define LH 1//左高,平衡因子为1。
#define EH 0//等高
#define RH -1//右高
typedef int datatype;
//定义平衡二叉树结点类型
typedef struct BBTNode {
datatype data;//数据域
int bf;//平衡因子域
4).绕某元素的右子节点右旋转,接着再绕该元素自己左旋转(RL)。
80 80 85
/ \右旋/ \左旋/ \
60 100 ------> 60 85 -------> 80 100
/ \ \ / / \
85 120 100 60 90 120
\ / \
90 90 120
a) BST树b) BST树c) AVL树
根据二叉查找树的特性可知:
如果插入结点小于某个结点,则必定是插入到这个结点的左子树中。
如果如果插入结点大于某个结点,则必定插入到这个结点的右子树中。
修改BF值的操作需从插入点开始向上回溯至根结点依次进行,当路径上某个结点BF值修改后变为0,则修改停止。
当结点的BF值由1或-1变为0,表明高度小的子树添加了新结点,树的高度没有增加,所以不必修改祖先结点的平衡因子。
c. AVL树的构造:
构造一棵平衡二叉树,需要动态地调整二叉查找树平衡,其方法为:
每插入一个结点后,首先检查是否破坏了树的平衡性,如果因插入结点而破坏了二叉查找树的平衡,则找出离插入点最近的不平衡结点。
然后将该不平衡结点为根的子树进行旋转操作,我们称该不平衡结点为旋转根,以该旋转根为根的子树称为最小不平衡子树。
b.算法实现:
int search(int array[], int n, int data)
{
int i;
if(array == NULL) return -1;//查找失败
for(i = 0; i < n; ++i) {
if(array[i] == data) return i;//查找成功
}
return -1;//查找失败
100 100 90
/ \左旋/ \右旋/ \
80 120 ------> 90 120 ------> 80 100
/ \ / / \ \
60 90 80 60 85 120
/ / \
85 60 85
a) BST树b) BST树c) AVL树
注:当树中节点X的左孩子的右孩子上插入新元素,且平衡因子从1变成2后,就需要先绕X的左子节点Y左旋转,接着再绕X右旋转。
bbt = rc;
}
//LR型调整
void LRRotate(bbtnode *bbt)
{
int low, mid, high, start, end, j;
low = 0;
high = n - 1;
while(low <= high) {//索引表的查找采用二分查找
mid = (low + high) / 2;
if(key <= i[mid].indexKey) high = mid - 1;
将n个数据元素"按块有序"划分为m块(m≤n)。每一块中的结点不必有序,但块与块之间必须"按块有序",即前一块中任一元素的关键字都必须小于后一块中任一元素的关键字。
同时根据所有块建立一张索引表,索引表中每一项由关键字字段(存放块中最大的元素的关键字)和指针字段(存放指向相应块的起始下标)组成。
查找分两个部分,先对索引表进行二分查找或顺序查找,以确定待查元素可能在哪一个块中,然后在已确定的块中顺序查找。
struct BBTNode *lchild, *rchild;//左右孩子指针域
}bbtnode;
//LL型调整
void rightRotate(bbtnode *bbt)
{
bbtnode *lc = NULL;
lc = bbt->lchild;//lc指向*bbt的左孩子
bbt->lchild = lc->rchild;
}
else end = i[low + 1].indexNum - 1;
//在块内顺序查找
for(j = start; j <= end; ++j) {
if(b[j].key == key) return j;//查找成功
}
}
return -1;//查找失败
}
int main()
{
int r;
blockList list[B] = {{8, 'a'}, {14, 'b'}, {6, 'c'}, {9, 'd'}, {10, 'e'}, {22, 'f'}, {34, 'g'}, {18, 'h'}, {19, 'i'}, {31, 'j'}};
相关文档
最新文档