数据结构笔记--总结各种查找算法及其应用
来源:互联网 发布:java微信 api好友列表 编辑:程序博客网 时间:2024/06/07 17:56
基于线性表的查找:具体分为顺序查找法、折半查找法以及分块查找法。三种方式都非常简单,在此引出一个概念,平均查找长度。即为了确定数据元素在列表中的位置,需和给定值进行比较的关键字个数的期望值,称为查找算法在查找成功时的平均查找长度。对于长度为n的列表,查找成功时的平均查找长度为ASL = P1C1 + P2C2 + P3C3 + … + PnCn = ∑PiCi (i=i..n) 其中Pi为查找列表中第i个元素的概率,Ci为找到列表中第i个元素时,已经进行过的关键字比较次数。那么顺序表的平均查找长度就是1/2(n+1),折半查找的平均查找长度为((n+1)/n)log(n+1)-1,当索引使用顺序查找时的分块查找的平均查找长度为1/2(n/s+s)+1,当索引使用二分查找是的平均查找长度为log(n/s+1)+s/2。其中表的长度为n,分为b块,每块含有s个元素。
// 二分查找,返回下标template<typename T>int BinSearch(T *array, int len, T key){ int lowIndex = 0, highIndex = len - 1; int midIndex = 0; while (lowIndex <= highIndex) { midIndex = (lowIndex + highIndex) / 2; if (key == array[midIndex]) return midIndex; else if (key < array[midIndex]) highIndex = midIndex - 1; else lowIndex = midIndex + 1; } return -1;}
基于树的查找:又称树表查找法,主要包括二叉排序树、平衡二叉排序树和B_树。这里主要介绍二叉排序树。
二叉排序树的插入:
1、若二叉排序树是空树,则key(待插入值)成为二叉排序树的根;
2、若二叉排序树非空,则将key与二叉排序树的根比较,如果key等于根节点的值,停止插入;
如果key小于根节点的值,则将key插入左子树;
如果key大于根节点的值,则将key插右左子树。
// 向二叉排序树中插入void InsertBT(BitTree **root, DataType key){ if ((*root) == NULL) { *root = new BitTree(); (*root)->m_data = key; (*root)->m_lchild = (*root)->m_rchild = NULL; } else { if (key < (*root)->m_data) { InsertBT(&(*root)->m_lchild, key); } else if (key >(*root)->m_data) { InsertBT(&(*root)->m_rchild, key); } }}
二叉排序树的删除:
1、若p(待删除的节点)为叶子节点,则可将其直接删除。
2、若p只有左子树,或者只有右子树,则可将p的左子树或右子树直接改为p的双亲节点的左子树。
3、若p既有左子树,又有右子树,则首先找到p的左子树中最大的值,并将其值赋给p节点,然后删掉这个最大值。偷梁换柱。
// 在二叉排序树中删除void DeleteBT(BitTree **root, DataType key){ BitTree *pCul = *root, *pParent = NULL; while (pCul != NULL) { if (key == pCul->m_data) { break; } pParent = pCul; if (key < pCul->m_data) { pCul = pCul->m_lchild; } else { pCul = pCul->m_rchild; } } if (pCul == NULL) { return; } if (pCul->m_lchild == NULL) { if (pParent == NULL) { *(root) = pCul->m_rchild; delete pCul; pCul = NULL; } else { if (pParent->m_lchild == pCul) { pParent->m_lchild = pCul->m_rchild; } else if (pParent->m_rchild == pCul) { pParent->m_rchild = pCul->m_rchild; } } delete pCul; pCul = NULL; } else { BitTree *pTempCul = pCul->m_lchild, *pTempParent = pCul; while (pTempCul->m_rchild != NULL) { pTempParent = pTempCul; pTempCul = pTempCul->m_rchild; } pCul->m_data = pTempCul->m_data; if (pCul == pTempParent) { pTempParent->m_lchild = pTempCul->m_lchild; } else { pTempParent->m_rchild = pTempCul->m_lchild; } delete pTempCul; pTempCul = NULL; } return;}
二叉排序树的平均查找长度为log n;
计算式查找法:哈希法
处理冲突的方法:1、开放定址法,当key的hash地址出现冲突时,以此地址为基础,在产生一个hash地址,直到不冲突为止。
2、再hash法,同时构造多个不同的hash函数,当hash地址发生冲突时,再使用另一个hash函数重新计算,并写入新表。
3、链地址法,将所有出现冲突的元素构成一个单链表。
4、建立公共溢出区,将hash表分为基本表与溢出表两部分,没发生冲突的放在基本表,否则放在溢出表。
拓展:查找一组序列中最小的K个数
将这组序列中前k个数维护成一个最大堆,然后遍历序列,将序列中的元素与最大堆的首元素进行比较,如果序列中的元素大于堆中的元素,那么他就一定大于堆中其他元素,即不是最小的k个数,丢弃。否则,交换。在STL中,set和multiset都是使用红黑树实现的,所以这两个容器可以用来模拟最大堆。multiset允许插入元素重复。
void SearchLeastNum(const vector<DataType> &array, const size_t k, multiset<DataType, greater<DataType>> &least){ least.clear(); if (k < 1 || array.size() < k) { return; } auto vIt = array.begin(); for (; vIt != array.end(); ++vIt) { // 先初始化一个包含K个元素的最大堆 if (least.size() < k) { least.insert(*vIt); } // 如果要插入的元素小于最大堆的最大值,替换 else { auto sIt = least.begin(); if (*vIt < *sIt) { least.erase(sIt); least.insert(*vIt); } } }}
- 数据结构笔记--总结各种查找算法及其应用
- 数据结构笔记--总结各种排序算法及其应用
- 数据结构之查找算法总结笔记
- 查找算法数据结构总结
- 数据结构-查找算法总结
- 《数据结构与算法》学习笔记10 栈及其应用
- 各种二分查找算法总结
- 各种排序、查找算法总结
- 常用数据结构及其应用总结
- 数据结构各种排序算法总结
- 数据结构各种排序算法总结
- 数据结构之查找算法总结
- 数据结构--七大查找算法总结
- 数据结构之查找算法总结
- 数据结构中的各种查找---总结篇
- 数据结构中的各种查找---总结篇
- 数据结构笔记之查找算法
- 数据结构笔记之查找算法
- 一个礼拜的学习总结
- Linux Ubuntu服务器用户权限及安全登陆限制
- Java基础——类成员
- Effective C++_Item5笔记
- 局部变量与全局变量
- 数据结构笔记--总结各种查找算法及其应用
- 数据结构笔记--实际软件开发中用到的最多的数据结构和算法
- POJ2135 Farm Tour 最小费用流
- 【Web容器】Tomcat源码分析(5)-请求原理分析(上)
- Linux-(C)IO多路复用之epoll学习(转载)
- 输入某年某月某日,判断这一天是这一年的第几天?
- Laravel安装记录
- XML解析之SAX解析
- 实例讲解虚拟机3种网络模式(桥接、nat、Host-only)