【数据结构】静态查找表的顺序表示

本文深入探讨数据结构中的查找技术,包括顺序查找、折半查找、次优查找树及分块查找,详细解析每种方法的时间复杂度与平均查找长度,为读者提供全面的理解与实践指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考资料:《数据结构(C语言版)严蔚敏著》
版权说明:未经作者允许,禁止转载。如引用本文内容,需标明作者及出处。如本文侵犯了您的权益,请联系我删除并致歉。
文章说明:如文章中出现错误,请联系我更改。如您对文章的内容有任何疑问,也欢迎来与我讨论。
本文正在施工中...请稍等...


静态查找表的顺序表示

typedef struct{
    ElemType *elem;    //数据元素存储空间基址
    int length;        //表长度
}SSTable;

一般顺序表的查找

顺序查找

从查找表中最后一个数据元素开始,逐个进行数据元素的关键字和给定值的比较,若某个数据元素的关键字和给定值比较相等,则查找成功,找到所查数据元素;反之,若直至第一个记录,其关键字和给定值比较都不等,则表明表中没有所查数据元素,查找不成功。

int Search(SSTable ST, KeyType key){
    //在顺序表ST中顺序查找其关键字等于key的数据元素,若找到,则函数值为该元素在表中的位置,否则为0
    ST.elem[0].key=key;
    for(i=ST.length; ST.elem[i].key!=key; i--);
    return i;
}

平均查找长度: ASL_{succ}=\sum_{i=1}^{n}P_{i}\times (n-i+1) ,ASL_{fail}=n+1
时间复杂度:O(n)

有序表的查找

顺序查找

平均查找长度: ASL_{succ}=\sum_{i=1}^{n}P_{i}\times (n-i+1) ,ASL_{fail}=n+1
时间复杂度:O(n)

折半查找

以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等于给定值或者查找区间的大小小于零时(表明查找不成功)为止。

int Serach(SSTable ST, KeyType key){
    //在有序表ST中折半查找其关键字等于key的数据元。若找到,则函数值为该元素在表中的位置,否则为0。
    low=1; high=ST.length;
    while(low<=high){
        mid=(low+high)/2;
        if(key==ST.elem[mid].key) return mid;
        else if(key<St.elem[mid].key) high=mid-1;
        else low=mid+1;
    }
    return 0;
}

 平均查找长度: ASL_{succ}=\frac{n+1}{n}log(n+1) ,ASL_{succ}=\frac{n+1}{n}log(n+1)
时间复杂度:O(logn)

静态树表的查找

对于一个按关键字有序的记录序列,构造一棵二叉树,使这棵二叉树的带权内路径长度PH值最小,称这类二叉树为静态最优二叉树。同样情况下,对于PH值近似最小的二叉树称为次优查找树。
PH=\sum_{i=1}^{n}w_{i}h_{i}
其中,n为二叉树上结点的个数,h_{i}为第i个结点在二叉树上的层次数;结点的权w_{i}=cp_{i}(i=1,2,...,n),其中p_{i}为结点的查找概率,c为某个常量。

构造次优查找树

已知一个按关键字有序的记录序列(r_{l},r_{l+1}, ..., r_{h}),其中r_{1}.key<r_{l+1}.key<...<r_{h}.key,每个记录对应的权值为w_{l},w_{l+1},...,w_{h}。构造次优查找树的步骤如下:

1、首先在该记录序列中取第i(l \leqslant i \leqslant h)个记录构造根结点r_{i},使得
\Delta P_{i}=|\sum_{j=i+1}^{h}w_{j}-\sum_{j=l}^{i-1}w_{j}|

取最小值。

2、然后分别对子序列(r_{l},r_{l+1},...,r_{i-1})(r_{i+1},r_{i+2},...,r_{h})构造两棵次优二叉树,并分别设为根结点r_{i}的左子树和右子树。

为便于计算\Delta P,引入累计权值和
sw_{i}=\sum_{j=l}^{i}w_{i}
并设w_{l-1}=0sw_{l-1}=0,则
sw_{i-1}-sw_{l-1}=\sum_{j=l}^{i-1}w_{j}sw_{h}-sw_{i}=\sum_{j=i+1}^{h}w_{j}
\Delta P_{i}=|(sw_{h}-sw_{i})-(sw_{i-1}-sw_{l-1})|=|(sw_{h}+sw_{l-1})-sw_{i}-sw_{i-1}|

void SecondOptimal(BiTree &T, ElemType R[], float sw[], int low, int high){
    i=low;
    min=abs(sw[high]-sw[low]);
    dw=sw[high]+sw[low-1];
    for(j=low+1; j<=high; ++j){
        if(abs(dw-sw[j]-sw[j-1])<min){
            i=j;
            min=abs(dw-sw[j]-sw[j-1]);
        }
    }
    T=(BiTree)malloc(sizeof(BiTNode));
    T->data=R[i];                                        //生成结点
    if(i==low) T->lchild=NULL;                           //左子树空
    else SecondOptimal(T->child, R, sw, low, i-1);       //构造左子树
    if(i==high) T->rchild=NULL;                          //右子树空
    else SecondOptimal(T->rchild, R, sw, i+1, high);     //构造右子树
}

typedef BiTree SOSTree;
Status CreateSOSTree(SOSTree &T, SSTable ST){
    if(ST.length==0) T=NULL;
    else{
        FindSW(sw, ST);
        SecondOptimal(T, ST.elem, sw, 1, ST.length);
    }
    return OK;
}

(由于在构造次优查找树的过程中,没有考虑单个关键字的相应权值,则有可能出现被选为根的关键字的权值比与它相邻的关键字的权值小。此时应作适当调整:选取邻近的权值较大的关键字作次优查找树的根结点。)

 从次优查找树的结构特点课件,其查找过程类似于折半查找。若次优查找树为空,则查找不成功,否则,首先将给定值key和其根结点的关键字相比,若相等,则查找成功,该根结点的记录即为所求;否则将根据给定值key小于或大于根结点的关键字而分别在左子树或右子树中继续查找直至查找成功或不成功为止。

索引顺序表的查找

分块查找

将记录序列划分为几个块,对每个块建立一个索引项,其中包括两项内容:关键字项(其值为该块内的最大关键字)和指针项(指示该块的第一个记录在整个记录序列中的位置)。由所有的索引项构成一个索引表,保证索引表按关键字有序,那么第二个块中所有记录的关键字大于第一个块中的最大关键字,第三个块中所有记录的关键字大于第二个块中的最大关键字,依次类推。分块查找过程需分两步进行,先确定待查记录所在的块,然后在块中顺序查找。

容易证明,当s取sqrt(n)时,ASL取最小值sqrt(n)+1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wingrez

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值