第六部分:查找

  • 查找基本概念

    • 静态查找表:仅作查询检索的操作
    • 动态查找表:在查找过程中对表进行动态修改
    • 查找算法评价指标: 关键字的平均比较次数(平均查找长度),ASL
  • 线性表的查找

    • 顺序查找(线性查找)

      • 应用:顺序表或线性链表

      • 数据元素类型定义:

        typedef struct {
          KeyType key;//关键字域
          InfoType otherinfo;//其他域
        } NodeType;
        typedef struct {
          NodeType *R;
          int length;
        } SSTable;
        
      • 算法描述:

        int Search_Seq(SSTable ST, KeyType key) {
          for (int i = ST.length; i >0; --i) {//0号位置不存储东西
            if (ST.R[i].key == key) {
              return i;
            }
          }
          return 0;
        }
        

        其他形式:

        int Search_Seq(SSTable ST, KeyType key) {
          for(i=S.length; i>0 && ST.R[i].key != key; --i) {
            return i;
          }
          return 0;
        }
        

        以上算法每一次循环都要进行两次比较,比较值是否相等且是否越界


        改进算法:把待查关键字存入表头

        int Search_Seq(SSTable ST, KeyType key) {
          ST.R[0].key = key;
          for (int i = ST.length; ST.R[i].key != key; --i) {
            return i;
          }
        }
        

        性能分析:

        1. 时间复杂度:O(n)
        2. 空间复杂度:O(1)
        3. ASL=(1+n)/2
    • 折半查找(二分或对分查找)
      算法描述:

      int Search_Bin(SSTable ST, KeyType key) {
        int low = 1, high = ST.length;
        while (low <= high) {
          int mid = (low + high) / 2;
          if (ST.R[mid].key == key) {
            return mid;
          } else if (ST.R[mid].key > key) {
            high = mid - 1;
          } else {
            low = mid + 1;
          }
        }
        return 0;
      }
      

      递归方法:

      int Search_Bin(SSTable ST, KeyType key, int low, int high) {
        if (low > high) {
          return 0;
        }
        int mid = (low + high) / 2;
        if (ST.R[mid].key == key) {
          return mid;
        } else if (ST.R[mid].key > key) {
          return Search_Bin(ST, key, low, mid - 1);
        } else {
          return Search_Bin(ST, key, mid + 1, high);
        }
      }
      

      性能分析:

      1. 时间复杂度:O(log2n)
      2. 空间复杂度:O(1)
      3. ASL=log2(n+1)-1
      4. 适用条件:顺序存储,有序表
    • 分块查找
      在这里插入图片描述


      三种方法比较:
      在这里插入图片描述

  • 树表的查找

    • 二叉排序树

      • 定义:左子树结点值<根结点值<右子树结点值,进过中序遍历后为从小到大排序
      • 二叉排序树的存储结构
        typedef struct{
          KeyType key;
          infoType otherinfo;
        }ElemType;
        typedef struct BSTNode{
          ElemType data;
          struct BSTNode *lchild, *rchild;
        }BSTNode, *BSTree;
        
        • 二叉排序树的查找
          递归查找:

          BSTNode *SearchBST(BSTree T, KeyType key) {
            if (!T || T->data.key == key) {
              return T;
            }
            if (key < T->data.key) {
              return SearchBST(T->lchild, key);
            } else {
              return SearchBST(T->rchild, key);
            }
          }
          

          在这里插入图片描述

        • 二叉排序树的操作

          • 插入

            void InsertBST(BSTree &T, ElemType e) {
              if (!T) {
                T = (BSTree)malloc(sizeof(BSTNode));
                T->data = e;
                T->lchild = T->rchild = NULL;
              } else if (e.key < T->data.key) {
                InsertBST(T->lchild, e);
              } else if (e.key > T->data.key) {
                InsertBST(T->rchild, e);
              }
            }
            

            在这里插入图片描述


            在这里插入图片描述

          • 删除

            1. 被删除的是叶子结点则直接删除
            2. 被删除的结点只有左子树或者右子树,直接替换
            3. 被删除的结点既有左子树也有右子树,则在左子树中找到最大值替换,也可以是右子树最小的结点替换
              在这里插入图片描述
            void DeleteBST(BSTree &T, KeyType key) {
              if (!T) {
                return;
              } else if (key < T->data.key) {
                DeleteBST(T->lchild, key);
              } else if (key > T->data.key) {
                DeleteBST(T->rchild, key);
              } else {
                if (T->lchild && T->rchild) {
                  BSTree q = T;
                  BSTree s = T->rchild;
                  while (s->lchild) {
                    q = s; s = s->lchild;
                  }
                  T->data = s->data;
                  if (q != T) {
                    q->lchild = s->rchild;
                  } else {
                    q->rchild = s->rchild;
                  }
                  free(s);
                } else {
                  BSTree q = T;
                  if (!T->lchild) {
                    T = T->rchild;
                  } else {
                    T = T->lchild;
                  }
                  free(q);
                }
              }
            }
            

            性能分析:在这里插入图片描述

    • 平衡二叉树(AVL树)

      • 平衡二叉树的定义

        • 左子树和右子树的高度差小于等于1
        • 左右子树都是平衡二叉树
      • 平衡二叉树的调整
        在这里插入图片描述

        • LL型

          在这里插入图片描述

在这里插入图片描述
+ RR型
在这里插入图片描述
在这里插入图片描述

  + LR型

在这里插入图片描述
在这里插入图片描述

  + RL型

在这里插入图片描述
在这里插入图片描述

  • 哈希表(散列表)的查找
    • 构造散列函数考虑的因素:
      1. 执行速度
      2. 关键字长度
      3. 散列表大小
      4. 关键字分布情况
      5. 查找频率
    • 哈希函数的构造方法
      1. 直接定址法:H(key)=a*key+b
      2. 除留余数法:H(key)=key mod p,设表长为m,取p<=m且为质数
      3. 数字分析法:取关键字的若干位作为散列地址
      4. 平方取中法:取关键字的平方的中间几位作为散列地址
      5. 折叠法:将关键字分割成位数相同的几部分,然后取这几部分的叠加和(舍去进位)作为散列地址
    • 处理冲突的方法
      1. 开放定址法
      • 线性探测法:H(key)=(H(key)+d) mod m,d=1,2,3,…
      • 二次探测法:H(key)=(H(key)+d^2) mod m,d=1,2,3,…
      • 随机探测法:H(key)=(H(key)+d) mod m,d为随机数
      1. 链地址法(拉链法)
        基本思想:将所有散列地址相同的记录存储在一个线性链表中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值