查找表(Search table)
静态查找表: 只进行查找操作
动态查找表: 在查找表上可以进行删除和插入操作
1.静态查找表的顺序查找
int Search_Seq(SSTable *T, KeyType key){
T->elem[0].key = key;
for(i = T->length;!EQ(T->elem[i].key,T->elem[0].key); --i);
return i;
}
2.有序表的查找
2.1折半查找 Binary Search
int Search_Bin(SSTable *T, KeyType key){
low = 1; high = T->length;
while(low <= high){ //low 跟 high可以相等,如果相等,意味着会是最后一次比较。
mid = (low + high)/2;
if(EQ(T->elem[mid],key)) return mid;
else if(LT(T->elem[mid],key)) low = mid +1;
else high = mid-1;
}
return 0;
}
可以用二叉树来描述折半查找的过程,这棵二叉树称为判定树。查找的次数是结点在树上的层次,最大的查找次数不过是树的层次。
2.2 斐波那契查找
2.3 适合关键字均匀分布的插值查找
3.静态树表的查找
如果记录被查找到的概率不同,查找性能最佳的是带权路径长度之和最小的二叉树,静态最优查找树。
静态最优查找树,是所有结点带权路径长度之和最小的查找树。其中权为每一个记录被查找到的概率。
最优二叉树,如赫夫曼树,是树的带权路径长度最小的树,是所有叶子结点的带权路径长度之和。
构造最优二叉查找树有些难度,转而构造次优二叉查找树Secondary Optimal Search Tree (SOSTree)
构造次优二叉查找树时,由于序列已经有序,只有尽量让左右子树权值和之差绝对值最小。
次优二叉查找树查找类似于折半查找,时间复杂度为O(logN)
typedef BiTree SOSTree;
//由有序表构造一棵次优查找树
Status CreateSOSTree(SOSTree *T,SSTable *ST){
if(ST->length == 0) T = NULL;
else{
FindSW(sw,ST); //建立ST各元素的累计权值表
SecondOptimal(T,ST.elem,sw,1,ST.length);
}
}
//差值计算方法: fabs(sw[high] + sw[low-1] - sw[j] - sw[j-1])
Status SecondOptimal(BiTree *T,ElemType R[],float sw[],int low,int high){
i = low; dw = sw[high] + sw[low-1];
min = fabs(sw[high]- sw[low]); //让min等于 i = low时的差值
for(j = low+1; j <= high; ++j){
if(min > fabs(dw - sw[j] - sw[j -1])){
min = fabs(dw - sw[j] - sw[j -1]);
i = j;
}
}
if(!(T = (BiTree)malloc(sizeof(BTNode)))) return OVERFLOW;
T->data = R[i];
if(i == low) T->lchild = NULL;
else SecondOptimal(T->lchild,T->lchild.R[],sw,int low,i-1);
if(i == high) T->rchild = NULL;
else SecondOptimal(T->rchild,T->rchild.R[],sw,int i+1,high);
return OK;
}
4.索引顺序表的查找
索引顺序查找 or 分块查找
索引表为每一个子表建立一个索引项,每一个索引项中包括关键字项和指针项。
关键字项: 子表中最大关键字 指针项: 指向子表中第一个记录
分块有序:在索引表中关键字项有序
分块查找的两个步骤:
1.在顺序索引表中查找到关键字所在的块 :对顺序表的查找
2.在所在块中查找记录 :对未知顺序的表查找
静态查找表: 只进行查找操作
动态查找表: 在查找表上可以进行删除和插入操作
1.静态查找表的顺序查找
int Search_Seq(SSTable *T, KeyType key){
T->elem[0].key = key;
for(i = T->length;!EQ(T->elem[i].key,T->elem[0].key); --i);
return i;
}
2.有序表的查找
2.1折半查找 Binary Search
int Search_Bin(SSTable *T, KeyType key){
low = 1; high = T->length;
while(low <= high){ //low 跟 high可以相等,如果相等,意味着会是最后一次比较。
mid = (low + high)/2;
if(EQ(T->elem[mid],key)) return mid;
else if(LT(T->elem[mid],key)) low = mid +1;
else high = mid-1;
}
return 0;
}
可以用二叉树来描述折半查找的过程,这棵二叉树称为判定树。查找的次数是结点在树上的层次,最大的查找次数不过是树的层次。
2.2 斐波那契查找
2.3 适合关键字均匀分布的插值查找
3.静态树表的查找
如果记录被查找到的概率不同,查找性能最佳的是带权路径长度之和最小的二叉树,静态最优查找树。
静态最优查找树,是所有结点带权路径长度之和最小的查找树。其中权为每一个记录被查找到的概率。
最优二叉树,如赫夫曼树,是树的带权路径长度最小的树,是所有叶子结点的带权路径长度之和。
构造最优二叉查找树有些难度,转而构造次优二叉查找树Secondary Optimal Search Tree (SOSTree)
构造次优二叉查找树时,由于序列已经有序,只有尽量让左右子树权值和之差绝对值最小。
次优二叉查找树查找类似于折半查找,时间复杂度为O(logN)
typedef BiTree SOSTree;
//由有序表构造一棵次优查找树
Status CreateSOSTree(SOSTree *T,SSTable *ST){
if(ST->length == 0) T = NULL;
else{
FindSW(sw,ST); //建立ST各元素的累计权值表
SecondOptimal(T,ST.elem,sw,1,ST.length);
}
}
//差值计算方法: fabs(sw[high] + sw[low-1] - sw[j] - sw[j-1])
Status SecondOptimal(BiTree *T,ElemType R[],float sw[],int low,int high){
i = low; dw = sw[high] + sw[low-1];
min = fabs(sw[high]- sw[low]); //让min等于 i = low时的差值
for(j = low+1; j <= high; ++j){
if(min > fabs(dw - sw[j] - sw[j -1])){
min = fabs(dw - sw[j] - sw[j -1]);
i = j;
}
}
if(!(T = (BiTree)malloc(sizeof(BTNode)))) return OVERFLOW;
T->data = R[i];
if(i == low) T->lchild = NULL;
else SecondOptimal(T->lchild,T->lchild.R[],sw,int low,i-1);
if(i == high) T->rchild = NULL;
else SecondOptimal(T->rchild,T->rchild.R[],sw,int i+1,high);
return OK;
}
4.索引顺序表的查找
索引顺序查找 or 分块查找
索引表为每一个子表建立一个索引项,每一个索引项中包括关键字项和指针项。
关键字项: 子表中最大关键字 指针项: 指向子表中第一个记录
分块有序:在索引表中关键字项有序
分块查找的两个步骤:
1.在顺序索引表中查找到关键字所在的块 :对顺序表的查找
2.在所在块中查找记录 :对未知顺序的表查找