数据结构笔记--总结各种查找算法及其应用
2016-07-30 19:24
585 查看
基于线性表的查找:具体分为顺序查找法、折半查找法以及分块查找法。三种方式都非常简单,在此引出一个概念,平均查找长度。即为了确定数据元素在列表中的位置,需和给定值进行比较的关键字个数的期望值,称为查找算法在查找成功时的平均查找长度。对于长度为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个元素。
基于树的查找:又称树表查找法,主要包括二叉排序树、平衡二叉排序树和B_树。这里主要介绍二叉排序树。
二叉排序树的插入:
1、若二叉排序树是空树,则key(待插入值)成为二叉排序树的根;
2、若二叉排序树非空,则将key与二叉排序树的根比较,如果key等于根节点的值,停止插入;
如果key小于根节点的值,则将key插入左子树;
如果key大于根节点的值,则将key插右左子树。
二叉排序树的删除:
1、若p(待删除的节点)为叶子节点,则可将其直接删除。
2、若p只有左子树,或者只有右子树,则可将p的左子树或右子树直接改为p的双亲节点的左子树。
3、若p既有左子树,又有右子树,则首先找到p的左子树中最大的值,并将其值赋给p节点,然后删掉这个最大值。偷梁换柱。
二叉排序树的平均查找长度为log n;
计算式查找法:哈希法
处理冲突的方法:1、开放定址法,当key的hash地址出现冲突时,以此地址为基础,在产生一个hash地址,直到不冲突为止。
2、再hash法,同时构造多个不同的hash函数,当hash地址发生冲突时,再使用另一个hash函数重新计算,并写入新表。
3、链地址法,将所有出现冲突的元素构成一个单链表。
4、建立公共溢出区,将hash表分为基本表与溢出表两部分,没发生冲突的放在基本表,否则放在溢出表。
拓展:查找一组序列中最小的K个数
将这组序列中前k个数维护成一个最大堆,然后遍历序列,将序列中的元素与最大堆的首元素进行比较,如果序列中的元素大于堆中的元素,那么他就一定大于堆中其他元素,即不是最小的k个数,丢弃。否则,交换。在STL中,set和multiset都是使用红黑树实现的,所以这两个容器可以用来模拟最大堆。multiset允许插入元素重复。
// 二分查找,返回下标 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); } } } }
相关文章推荐
- 数据结构笔记--总结各种排序算法及其应用
- 线段树专题#6_蒟蒻训练历程记录_HDU 2705 Billboard_单点更新
- 数据结构的知识总结-概论(1)
- 数据结构---二叉树的前序、中序、后序遍历的递归和非递归 实现(C++)
- 数据结构实验之栈二:一般算术表达式转换成后缀式
- poj2377 Bad Cowtractors (最大生成树)
- 数组结构体实现稀疏矩阵转置 (sdut oj 3347)
- 数据结构上机测试2-2:单链表操作B
- 数据结构实验之栈三:后缀式求值
- 数据结构实验之栈八:栈的基本操作
- 数据结构实验之栈三:后缀式求值
- PAT 1013. Battle Over Cities
- 遍历二叉树
- 数据结构实验之栈六:下一较大值(二)
- 数据结构实验之链表一:顺序建立链表
- SDUT2134数据结构实验之栈四:括号匹配(栈)
- 红黑树是什么鬼!!!
- 并查集
- sdut oj1479 数据结构实验之栈:行编辑器
- SDUT3335数据结构实验之栈八:栈的基本操作(栈)