数据结构的查找


1.  查找分类

        1.1  比较式查找法

                    1.1.1  线性表查找法

                                    1.1.1.1  顺序查找法

                                    1.1.1.2  折半查找法

                                    1.1.1.3  分块查找法

                    1.1.2  基于树的查找法

                                    1.1.2.1  二叉排序树

                                    1.1.2.2  平衡二叉树

        1.2  计算式查找法

                    1.2.1  哈希查找法


2. 算法实例

         2.1  顺序查找法

                思想:在表的一端设置监视哨(存放要查找的关键字),在表的另一段开始查找

                代码实现 sequence.c(完整代码)

/* 查找 key 键 */
int seq_search (RecordList l, int key) 
{
    /* 将键值设置在链的末端 */
    l.r[l.length].key = key;
    int     i;
    
    /* 顺序查找 */
    for (i = 0; l.r[i].key != key; i++) ;
    return i;
}
              平均查找长度:ASL = (n+1)/2

        2.2  折半查找法(序列必须排序)

                思想:比较中间键值,如果小于则把左边当作新序列比较中间键值,如果大于则把右边当作新序列比较中间键值。

                代码实现 binary.c(完整代码)

/* 查找 key 键, l 中的 r 数组必须按照key值的字典顺序排序 */
int binary_search (RecordList l, int key) 
{
    int     low = 0;
    int     high = l.length-1;

    while (low < high) {
        int     mid = (low + high)/2;
        if (key == l.r[mid].key) 
            return mid;
        else if (key < l.r[mid].key) 
            high = mid - 1;
        else 
            low = mid + 1;
    }
    
    return l.length;
}

              平均查找长度:ASL = log 2 (n+1) - 1



        2.3  分块查找法

                思想:首先将列表分成若干个块(子列表,块间有序,快内无序),构造一个索引表,索引表按键值有序排列

                代码实现 block.c(完整代码)

int block_search (RecordList l, int key)
{
    BlockList (BLOCK_SIZE, l.length, 1); 

    int     i; 
    for (i = 0; i < block_list1.length; i++) {
        block_list1.r[i].addr = i * block_list1.block_length;
        block_list1.r[i].max_key = l.r[i*5].key;
    }

    for (i = 0; i < l.length; i++) 
        if (block_list1.r[i/5].max_key < l.r[i].key)
            block_list1.r[i/5].max_key = l.r[i].key;
    
    for (i = 0; i < block_list1.length; i++) {
        if (key < block_list1.r[i].max_key) {
            l.list_s = block_list1.r[i].addr;
            l.list_e = (i == block_list1.length-1 ? 
                        l.length : block_list1.r[i+1].addr-1);
            return seq_search (l, key);
        }
    }

    return l.length;
}
              平均查找长度:ASL = log 2 (n/s+1) + s/2             n 表示表的长度,s表示每块中的

        2.4  二叉排序树的查找法

                思想:key 和跟结点 t.key 比较 ,如果相等则返回根,小于进一步查左子树,大于进一步查右子树

                代码实现 binary_tree.c(完整代码)

/* 二叉排序树的查找 */
BSTree BST_search (const BSTree root, int key) 
{
    if (!root) return NULL; 
    else if (root->data.key == key) 
        return root; 
    else if (key < root->data.key) 
        return BST_search (root->LChild, key); 
    else 
        return BST_search (root->RChild, key); 
} 


        2.5  平衡二叉树(AVL树)

               思想:对失衡节点进行顺时针或逆时针旋转

                           有四种形式:LL、LR、RR、RL

                                                   假设失衡节点为 A、它的孩子节点中的某个为B 、他的孩子的孩子节点中的某个节点为C,

                                                   则:LL:(B为A的左孩子)对A做一次顺时针旋转

                                                           RR:(B为A的右孩子)对A做一次顺时针旋转

                                                           LR:(B为A的左孩子,C为B的右孩子)对B做一次逆时针旋转,对A做一次顺时针旋转

                                                           RL:(B为A的右孩子,C为B的左孩子)对B做一次顺时针旋转,对A做一次、逆时针旋转

                代码实现 AVLTree.c(完整代码)

/* 平衡二叉树插入节点 */
void ins_AVLTree (AVLTree *avlt, int key)
{
    /* 初始化一个新节点 */
    AVLTNode    *S = (AVLTree)malloc (sizeof (AVLTNode));
    S->data.key = key;
    S->LChild = S->RChild = NULL;
    S->bf = 0;

    /* 插入 */
    if (!*avlt) 
        *avlt = S;
    else {
        /* 首先查找S的插入位置fp,同时记录距S的插入位置最近且
         * 平衡因子不等于0(等于-1或1)的节点A, A可能为失衡节点 */
        AVLTNode *A = *avlt, *FA = NULL;
        AVLTNode *p = *avlt, *fp = NULL;

        while (p) {
            if (p->bf) {
                A = p; 
                FA = fp;
            }
            fp = p;

            if (key < p->data.key) 
                p = p->LChild;
            else 
                p = p->RChild;
        }

        /* 插入S */
        if (key < fp->data.key) 
            fp->LChild = S; 
        else if (key > fp->data.key)
            fp->RChild = S; 
        else {
            free (S);
            return;
        }

        /* 确定节点B,并修改A的平衡因子 */ 
        AVLTNode    *B; 
        if (key < A->data.key) { 
            B = A->LChild; 
            A->bf += 1; 
        }else { 
            B = A->RChild; 
            A->bf -= 1; 
        }

        /* 修改B到S路径上各节点的平衡因子 */
        p = B; 
        while (p != S) { 
            if (key < p->data.key) { 
                p->bf = 1; 
                p = p->LChild; 
            }else { 
                p->bf = -1; 
                p = p->RChild; 
            }
        } 

        /* 判断失衡类型并做相应处理 */
        /* LL型 */
        if (2 == A->bf && 1 == B->bf) {
            /* A做一次顺时针旋转 */
            B = A->LChild;
            A->LChild = B->RChild;
            B->RChild = A;
            A->bf = B->bf = 0; 

            if (!FA) 
                *avlt = B;
            else if (A == FA->LChild)
                FA->LChild = B;
            else 
                FA->RChild = B;
        } /* LR型 */
        else if (2 == A->bf && -1 == B->bf) {
            AVLTNode *C;
            /* 先对B做一次逆时针旋转,再对A做一次顺时针旋转 */
            B = A->LChild;
            C = B->RChild;
            B->RChild = C->LChild;
            A->LChild = C->RChild;
            C->LChild = B;
            C->RChild = A;

            if (S->data.key < C->data.key) {
                A->bf = -1; B->bf = C->bf = 0;
            }else if (S->data.key > C->data.key) {
                B->bf = 1; A->bf = C->bf = 0;
            }else 
                A->bf = B->bf = 0; 

            if (!FA) 
                *avlt = S;
            else if (A == FA->LChild) 
                FA->LChild = C;
            else 
                FA->RChild = C;
        } /* RL型 */
        else if (-2 == A->bf && 1 == B->bf) {
            AVLTNode *C;
            /* 先对B做一次顺时针旋转,再对A做一次逆时针旋转 */ 
            B = A->RChild;
            C = B->LChild;
            B->LChild = C->RChild;
            A->RChild = C->LChild;
            C->LChild = A;
            C->RChild = B;

            if (S->data.key < C->data.key) {
                B->bf = -1; A->bf = C->bf = 0;
            }else if (S->data.key > C->data.key) {
                A->bf = 1; B->bf = C->bf = 0;
            }else 
                A->bf = B->bf = 0;

            if (!FA) 
                *avlt = S;
            else if (A == FA->LChild) 
                FA->LChild = C;
            else 
                FA->RChild = C;
        } /* RR 型 */
        else if (-2 == A->bf && -1 == B->bf) {
            /* 对A做一次逆时针旋转 */
            B = A->RChild;
            A->RChild = B->LChild;
            B->LChild = A;
            A->bf = B->bf = 0;

            if (!FA) 
                *avlt = B;
            else if (A == FA->LChild) 
                FA->LChild = B;
            else 
                FA->RChild = B;
        }
    }
}
              时间复杂度:O(log 2 n)




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值