查找
一、线性表的查找
顺序查找
从表的一端开始,依次将记录的关键字和给定的值进行比较,时间复杂度为O(n)
算法简单,对表结构没有任何要求,既适用于顺序结构,也适用于链式结构
缺点:平均查找长度较大,查找效率较低
折半查找
折半查找要求线性表必须采取顺序结构,而且表中元素按照关键字有序排列时间复杂度为O(log2n)
`#include<iostream>`
`#include<map>`
`#define maxsize 100`
`using namespace std;`
`typedef struct {`
`int key;`
`string name;`
`char sex;`
`int age;`
`}ElemType;`
`typedef struct {`
`ElemType* elem;`
`int length;`
`}SSTable;`
`string name[11] = { "Zhang" ,"Wang","Zhou","Huang","Zheng","Li","Liu","Qian","Sun","Zhao","Chen"};`
`int key[11] = {56,19,80,5,21,64,88,13,37,75,92};`
`char sex[11] = {'F','F','F','M','M','M','F','F','M','M','M'};`
`int age[11] = {19,20,19,20,20,19,18,19,20,20,20};`
`void CreateSSTable(SSTable& S, int n) {`
`if (n > maxsize) {`
`cout << "字符的长度过大";`
`return;`
`}`
`S.elem = new ElemType[n];`
`for (int i = 0; i < n; i++) {`
`S.elem[i].age = age[i];`
`S.elem[i].key = key[i];`
`S.elem[i].name = name[i];`
`S.elem[i].sex = sex[i];`
`}`
`S.length = n;`
`}`
`void TraversSSTable(SSTable S) {`
`cout << "学号 姓名 年龄 性别" << endl;`
`for (int i = 0; i < S.length; i++) {`
`cout << S.elem[i].key << " " << S.elem[i].name << " " << S.elem[i].age << " " << S.elem[i].sex << endl;`
`}`
`return;`
`}`
`int SearchSSTable_Seq(SSTable S, int key, int& c) {`
`int i = 0;`
`while (i <= S.length) {`
`if (key == S.elem[i].key) {`
`c++;`
`cout << "查找成功";`
`cout << S.elem[i].key << " " << S.elem[i].name << " " << S.elem[i].age << " " << S.elem[i].sex << endl;`
`cout << "下标为" << i << endl;`
`cout << "比较次数:" << c << endl;`
`return 1;`
`}`
`else {`
`c++;`
`i++;`
`}`
`}`
`cout << "查找失败";`
`return 0;`
`}`
`void SortSSTable(SSTable& S) {`
`ElemType Temp;`
`int j;`
`for (int i = 0; i < S.length; i++) {`
`Temp = S.elem[i];`
`j = i - 1;`
`while (j >= 0 && Temp.key < S.elem[j].key) {`
`S.elem[j + 1] = S.elem[j];`
`--j;`
`}`
`S.elem[j + 1] = Temp;`
`}`
`}`
`int SearchSSTable(SSTable S, int key, int& c) {`
`int center = S.length / 2;`
`int head = 0;`
`int tail = S.length;`
`if (key<S.elem[0].key || key>S.elem[S.length - 1].key) {`
`cout << "你输入的数据不在查找范围";`
`return 0;`
`}`
`while (head <= tail) {`
`if (S.elem[center].key < key) {`
`head = center + 1;`
`c++;`
`}`
`else if (S.elem[center].key == key) {`
`cout << "查找到" << S.elem[center].key << " " << S.elem[center].name << " " << S.elem[center].age << " " << S.elem[center].sex << endl;`
`cout << "比较次数" << c << endl;`
`c++;`
`break;`
}
else {
tail = center - 1;
c++;
}
center = (head + tail) / 2;
}
if (head > tail) {
cout << "没有找到该学员";
}
`}`
`int main() {`
`int key2[10] = { 111,198,157,164,187,124,35,852,987,333 };`
`int key1;`
`int c1 = 0;`
`int c = 0;`
`SSTable S;`
`CreateSSTable(S, 10);`
`TraversSSTable(S);`
`cout << "请输入你要顺序查找对象的学号"<<endl;`
`cin >> key1;`
`SearchSSTable_Seq(S, key1, c1);`
`SortSSTable(S);`
`TraversSSTable(S);`
cout << "请输入你要二分查找对象的学号输入-1结束循环" << endl;
cin >> key1;
while (key1 != -1) {
c = 0;
SearchSSTable(S, key1, c);
cin >> key1;
}
for (int i = 0; i < 11; i++) {
c = 0;
SearchSSTable(S, key[i], c);
}
for (int i = 0; i < 10; i++) {
c = 0;
SearchSSTable(S, key2[i], c);
}
return 0;
`}`
分块查找(索引顺序查找)
可以将一个表分为多个子表,对每个子表建立一个索引项,其中包括两项内容:关键字项(此表内的最大关键字)和指针项(指示该子表的第一个记录在表中的位置)
分块有序:索引表按关键字有序,第二的子表中的所有记录关键字均大于第一个子表中的关键字,依次类推。
索引表有序排列,可以用二分查找或者顺序查找,块内查找用顺序查找
分块查找于哈希查找相似(索引表和哈希函数类似,可以说分块查找是哈希的特殊形式)
tip:个人认为分块查找的应用性不大,如果需要保证索引表的有序性,并且满足子表之间的大小关系排布,需要进行排序,但是排序以后,可以直接使用二分查找,效率更高;如果先确定索引表,那么再插入匀速的时候,很可能出现索引无效,可以直接用哈希表代替。
二、树表的查找
二叉排序树
1、若他的根节点不空,则左子树上的所有节点的值均小于他的根节点上的值
2、若他的右子树不空,则右子树上的所有节点的值均大于他的根节点上的值
3、他的左右子树也可以被看作二叉排序树
在二叉树上进行查找操作于折半查找类似,也是一个逐步缩小查找范围的过程
`#include<iostream>`
`#include<stack>`
`#include <windows.h>`
`#include<string>`
`using namespace std;`
`struct TreeNode {`
`int data;`
`string name;`
`string sex;`
`int age;`
`int time = 0;`
`TreeNode* pParent;`
`TreeNode* pLeft;`
`TreeNode* pRight;`
`};`
`TreeNode* pRoot = NULL;`
`TreeNode* find(TreeNode* root, char const& findData,int &time) {`
`if (root) {`
`time++;`
`if (root->data == findData) {`
`return root;`
`}`
`else if (findData < root->data) {`
`return find(root->pLeft, findData,time);`
`}`
`else {`
`return find(root->pRight, findData, time);`
`}`
`}`
`return nullptr;`
`}`
`void InOrderTraverse(TreeNode* pRoot) {//递归中序遍历`
`if (pRoot == NULL) {`
`return;`
`}`
`InOrderTraverse(pRoot->pLeft);`
`if (pRoot->data != -1) {`
`cout << pRoot->data << " " << pRoot->name << " " << pRoot->age << " " << pRoot->sex << endl;`
`}`
`InOrderTraverse(pRoot->pRight);`
`}`
`void insert(TreeNode* pRoot, int const& insertData, char const& findData, bool isLeft) {`
`TreeNode* tempInsertNode = new TreeNode;`
`tempInsertNode->data = insertData;`
`tempInsertNode->pParent = nullptr;`
`tempInsertNode->pLeft = nullptr;`
`tempInsertNode->pRight = nullptr;`
`int number = 0;`
`if (pRoot) {`
`TreeNode* findNode = find(pRoot, findData,number);`
`if (findNode) {`
`if (isLeft) {`
`findNode->pLeft = tempInsertNode;`
`tempInsertNode->pParent = findNode;`
`}`
`else {`
`findNode->pRight = tempInsertNode;`
`tempInsertNode->pParent;`
`}`
`}`
`else {`
`TreeNode* tempNode = pRoot;`
`while (tempNode->pLeft) {`
`tempNode = tempNode->pLeft;`
`}`
`tempNode->pLeft = tempInsertNode;`
`tempInsertNode->pParent = tempNode;`
`}`
`}`
`else {`
`pRoot = tempInsertNode;`
`}`
`}`
`int High(TreeNode* pRoot) {`
`if (pRoot == NULL)`
`return -1;`
`else {`
`return 1 + max(High(pRoot->pLeft), High(pRoot->pRight));`
`}`
`}`
`void _clear(TreeNode* root) {`
`if (root) {`
`_clear(root->pLeft);`
`_clear(root->pRight);`
`delete root;`
`root = nullptr;`
`}`
`}`
`void CMyTree_List(TreeNode* pRoot) {`
`pRoot->pLeft = nullptr;`
`pRoot->pRight = nullptr;`
`pRoot->pParent = nullptr;`
`}`
`TreeNode* BSTiinsert(TreeNode*& pRoot, int n, int age, string name, string sex) {
if (pRoot == NULL) {
TreeNode* temp = new TreeNode;`
`temp->data = n;`
`temp->age = age;`
`temp->name = name;`
`temp->sex = sex;`
`temp->pLeft = NULL;`
`temp->pRight = NULL;`
`pRoot = temp;`
`}`
`else {`
`if (n < pRoot->data) {`
`pRoot->pLeft = BSTiinsert(pRoot->pLeft, n, age, name, sex);`
`}`
`else {`
`pRoot->pRight = BSTiinsert(pRoot->pRight, n, age, name, sex);`
`}`
`}`
`return pRoot;`
`}`
`void CreateBST(TreeNode*& pRoot, const int* arr, int* age, string* name, string* sex, int number) {`
for (int i = 0; i < number; i++) {
cout << arr[i] << endl;
BSTiinsert(pRoot, arr[i], age[i], name[i], sex[i]);
}
`}`
`void TNodes(TreeNode* pRoot, int& no, int& one, int& two) {`
if (pRoot == NULL) {
return;
}
if (pRoot->pLeft != nullptr && pRoot->pRight != nullptr) {
two++;
}
if (pRoot->pLeft == nullptr && pRoot->pRight == nullptr) {
no++;
}
if (((pRoot->pLeft == nullptr) && (pRoot->pRight != nullptr)) || ((pRoot->pLeft != nullptr) && (pRoot->pRight == nullptr))) {
one++;
}
TNodes(pRoot->pLeft, no, one, two);
TNodes(pRoot->pRight, no, one, two);
`}`
`void DeleteDSTable_BST(TreeNode*& pRoot, int finddata) {
int number = 0;
TreeNode* T1 = find(pRoot, finddata,number);`
`if (T1) {`
`T1->data = -1;`
`}`
`else {`
`cout << "你输入的学生不存在,请重新输入";`
`}`
`}`
`int main() {`
`TreeNode* pRoot = NULL;`
`int n;`
`int data;`
`int age1;`
`string name1;`
`string sex1;`
`TreeNode* T1 = new TreeNode;`
`TreeNode* T2 = NULL;`
`int no = 0, one = 0, two = 0;`
`int high;`
`int arr[11] = { 56,19,80,5,21,64,88,13,37,75,92 };`
`string name[11] = { "zhang","wang","zhou","huang","zheng","li","liu","qian","sun","zhao","chen" };`
`string sex[11] = { "F","F","F","M","M","M","F","F","M","M","M" };`
`int age[11] = { 19,20,19,20,20,19,18,19,20,20,20 };`
CreateBST(pRoot, arr, age, name, sex, 11);
InOrderTraverse(pRoot);
cout << "请输入插入学生的信息:(学号,年龄,姓名,性别)输入-1时代表插入结束" << endl;
cin >> n >> age1 >> name1 >> sex1;
while (n != -1) {
int time3 = 0;
TreeNode* p = find(pRoot, n, time3);
BSTiinsert(pRoot, n, age1, name1, sex1);
InOrderTraverse(pRoot);
cin >> n >> age1 >> name1 >> sex1;
}
cout << "请输入查找人的学号:" << endl;
cin >> data;
while (data != -1) {
int time = 0;
T2 = find(pRoot, data,time);
if (T2) {
cout << T2->data << " " << T2->name << " " << T2->sex << " " << T2->age<<"比较次数为" <<time<< endl;
}
else {
cout << "您输入的学号不存在";
}
cin >> data;
}
double sum = 0;
for (int i = 0; i < 11; i++) {
int time1 = 0;
T2 = find(pRoot, arr[i], time1);
if (T2) {
cout << T2->data << " " << T2->name << " " << T2->sex << " " << T2->age << "比较次数为" << time1 << endl;
sum = sum + time1;
}
else {
cout << "您输入的学号不存在";
}
}
double ASL = sum/ 11;
cout << "ASL " << ASL;
cout << "请输入你要删除人的学号:" << endl;
cin >> n;
while (n != -1) {
DeleteDSTable_BST(pRoot, n);
InOrderTraverse(pRoot);
cin >> n;
}
`}`
平衡二叉树
二叉查找算法的性能取决于二叉树的结构,而二叉排序树的形状则取决于其数据集
如果数据呈现有序排列,则二叉树是线性的,查找的时间复杂度是O(n);反之,如果二叉排序树的结构合理,则查找速度较快,查找的时间复杂度为log2n,平衡二叉树就是尽可能的减少二叉树的高度,来提高算法的效率。
平衡二叉树的特点:
左子树和右子树的深度之差的绝对值不超过1
左子树和右子树也是平衡二叉树
平衡因子:该节点左子树和右子树的深度之差,平衡二叉树所有节点的平衡因子只可能是-1,0,1#include<iostream>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vddr58fB-1622456745177)(C:\Users\Lenovo\Desktop\备份\平衡二叉树LL转换.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1X77e7Pn-1622456745186)(C:\Users\Lenovo\Desktop\备份\平衡二叉树LR转换.png)]
`#include<Cstdlib>`
`#include<cmath>`
`using namespace std;`
`template<class ElementType>`
`struct Node {`
`ElementType data;`
`struct Node* lChild;`
`struct Node* rChild;`
`int balanceFctor;`
`};`
`template <class ElementType>`
`class BalanceBiTree {`
`public:`
`BalanceBiTree(Node<ElementType>*& T); //初始化
static void menu(); //菜单
void destory(Node<ElementType>*& T); //销毁二叉树`
`void insert(Node<ElementType>*& T, Node<ElementType>* S); //将指针S所指节点插入二叉排序中`
`int BiTreeDepth(Node <ElementType>* T); //求树的高度`
`int getNodeFactor(Node<ElementType>* T); //求树中节点的平衡因子`
`void factorForTree(Node<ElementType>*& T); //求树中的每个节点的平衡因子
void nodeFctorIsTwo(Node<ElementType>*& T, Node<ElementType>*& p); //获得平衡因子为2或-2的节点
void nodeFctorIsTwoFather(Node<ElementType>*& T, Node<ElementType>*& f); //获得平衡因子为2或-2的节点的父节点
void LLAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f); //LL调整`
`void LRAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f); //LR调整
void RLAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f); //RL调整`
`void RRAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f); //RR调整
void AllAdjust(Node<ElementType>*& T); //集成四种调整,并实时更新平衡因子`
`void preOrderTraverse(Node<ElementType>* T, int level); //先序遍历输出`
`void inOrderTraverse(Node <ElementType>* T, int level); //中序遍历输出`
`void BiTreeToArray(Node <ElementType>* T, ElementType A[], int i, int& count); //二叉树转数组`
`void LevelTraverse(Node <ElementType>* T, ElementType B[], int num); //对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印`
`void createSubBalanceBiTree(Node<ElementType>*& T); //交互创建二叉平衡树
void createBalanceBiTreeFromArray(Node<ElementType>*& T, ElementType A[], int n);//从数组中创建平衡二叉树`
`void search(Node <ElementType>*& T, Node <ElementType>*& p, ElementType x); //查找元素x`
`Node <ElementType>* getElementFatherPointer(Node <ElementType>*& T, Node <ElementType>*& f, ElementType x); //获取某个元素的父亲指针,不存在返回NULL`
`void getPriorElement(Node <ElementType>*& T, ElementType& min, ElementType& max); //获取前驱元素
Node <ElementType>* getElementPriorPointer(Node <ElementType>*& T); //获取某个元素的前驱指针
void getNextElement(Node <ElementType>*& T, ElementType& min, ElementType& max); //获取后继元素`
`Node <ElementType>* getElementNextPointer(Node <ElementType>*& T); //获取某个元素的后继指针
void deleteLeafNode(Node <ElementType>*& T, Node <ElementType>*& p, Node <ElementType>*& f); //删除叶子节点`
`void deleteOneBranchNode(Node <ElementType>*& T, Node <ElementType>*& p, Node <ElementType>*& f); //删除仅有左子树或只有右子树的节点
void deleteTwoBranchNode(Node <ElementType>*& T, Node <ElementType>*& p); //删除既有左子树又有右子树的节点
void deleteOperate(Node <ElementType>*& T, ElementType x); //集成删除的三种情况的操作`
`private:`
`Node<ElementType>* root; //树根`
`};`
`//初始化`
`template< class ElementType>`
`BalanceBiTree<ElementType>::BalanceBiTree(Node<ElementType>*& T)//构造函数,创建一个空的平衡二叉树
{
T = NULL;
}
//菜单
template< class ElementType>
void BalanceBiTree<ElementType>::menu()//菜单函数,提供功能菜单
{
cout << "*************************************************" << endl;
cout << "0退出并销毁平衡二叉树" << endl;
cout << "1二分查找算法实现查找元素" << endl;
cout << "2插入结点构建二叉排序树(二叉平衡树)" << endl;
cout << "3二叉排序树中查找指定值的结点" << endl;
cout << "4二叉排序树中删除特定值的结点" << endl;
cout << "5数组A[1..26]递增有序,设计算法以构造一棵平衡的二叉排序树" << endl;
cout << "6树形输出" << endl;
cout << "*************************************************" << endl;
}
//销毁二叉树
template< class ElementType>
void BalanceBiTree<ElementType>::destory(Node<ElementType>*& T)`
`{`
`if (T)//如果二叉树非空`
`{`
`destory(T->lChild);//删除二叉树的左子树`
`destory(T->rChild);//删除二叉树的右子树`
`delete T;`
`}`
`}`
`//将指针S所指节点插入二叉排序中`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::insert(Node<ElementType>*& T, Node<ElementType>* S)`
`{`
`if (T == NULL)//如果二叉树为空二叉树,则把节点插入到根节点位置`
`T = S;`
`else if (S->data < T->data)//二叉搜索树插入方式,如果插入节点的值小于当前指针所指的值,则插入到左子树中`
`insert(T->lChild, S);`
`else//如果插入节点的值大于当前指针所指的值,则插入到右子树中`
`insert(T->rChild, S);`
`}`
`//求树的高度`
`template< class ElementType>`
`int BalanceBiTree<ElementType>::BiTreeDepth(Node <ElementType>* T)`
`{`
`int m, n;`
`if (T == NULL)`
`return 0; //空树,高度为0`
`else {`
`m = BiTreeDepth(T->lChild); //求左子树高度(递归)`
`n = BiTreeDepth(T->rChild); //求右子树高度(递归)`
`if (m > n)//左子树高度较大,则输出左子树高度`
`{`
`return m + 1;//加上根节点`
`}`
`else {`
`return n + 1;`
`}`
`}`
`}`
`//求树中节点的平衡因子,从树中节点开始计算,不一定从根节点开始计算`
`template< class ElementType>`
`int BalanceBiTree<ElementType>::getNodeFactor(Node<ElementType>* T)`
`{`
`int m = 0, n = 0;`
`if (T)`
`{`
`m = BiTreeDepth(T->lChild);///左子树高度`
`n = BiTreeDepth(T->rChild);//右子树高度`
`}`
`return m - n;//左右子树的高度差`
`}`
`//求树中的每个节点的平衡因子`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::factorForTree(Node<ElementType>*& T)
{
if (T)
{
T->balanceFctor = getNodeFactor(T);//获得根节点的平衡因子
factorForTree(T->lChild);//左子树的平衡因子
factorForTree(T->rChild);//右子树的平衡因子
}
}
//获得平衡因子为2或-2的节点,每次只会反回一个节点
template< class ElementType>
void BalanceBiTree<ElementType>::nodeFctorIsTwo(Node<ElementType>*& T, Node<ElementType>*& p)
{
if (T)
{
if (T->balanceFctor == 2 || T->balanceFctor == -2)
{
p = T;
}
nodeFctorIsTwo(T->lChild, p);//左子树
nodeFctorIsTwo(T->rChild, p);//右子树
}
}
//获得平衡因子为2或-2的节点的父节点
template< class ElementType>
void BalanceBiTree<ElementType>::nodeFctorIsTwoFather(Node<ElementType>*& T, Node<ElementType>*& f)`
`{`
`if (T)`
`{`
`if (T->lChild != NULL)//左子树非空`
`{`
`if (T->lChild->balanceFctor == 2 || T->lChild->balanceFctor == -2)`
`{`
`f = T;`
`}`
`}`
`if (T->rChild != NULL)`
`{`
`if (T->rChild->balanceFctor == 2 || T->rChild->balanceFctor == -2)`
`{`
`f = T;`
`}`
`}`
`nodeFctorIsTwoFather(T->lChild, f);//递归左子树`
`nodeFctorIsTwoFather(T->rChild, f);//递归右子树`
`}`
`}`
`//LL调整,二叉树中出现连续三个左节,当前节点平衡节点为2,左子树节点不为2`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::LLAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f)
{
Node<ElementType>* r;`
`if (T == p) //->balanceFctor==2&&T->lChild->balanceFctor!=2`
`{`
`cout << "LL调整" << endl;`
`T = p->lChild; //将P的左孩子提升为新的根节点`
`r = T->rChild;`
`T->rChild = p; //将p降为其左孩子的右孩子`
`p->lChild = r; //将p原来的左孩子的右孩子连接其p的左孩子`
}
else {
if (f->lChild == p) //f的左孩子是p
{
cout << "LL调整" << endl;
f->lChild = p->lChild; //将P的左孩子提升为新的根节点
r = f->lChild->rChild;
f->lChild->rChild = p; //将p降为其左孩子的右孩子
p->lChild = r; //将p原来的左孩子的右孩子连接其p的左孩子
}
if (f->rChild == p) //f的右孩子是p
{
cout << "LL调整" << endl;
f->rChild = p->lChild; //将P的左孩子提升为新的根节点
r = f->rChild->rChild;
f->rChild->rChild = p; //将p降为其左孩子的右孩子
p->lChild = r; //将p原来的左孩子的右孩子连接其p的左孩子
}
}
`}`
`//LR调整`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::LRAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f)
{
Node<ElementType>* l, * r;`
`if (T == p) //->balanceFctor==2&&T->lChild->balanceFctor!=2`
`{`
`cout << "LR调整" << endl;`
`T = p->lChild->rChild; //将P的左孩子的右孩子提升为新的根节点`
`r = T->rChild;`
`l = T->lChild;`
`T->rChild = p;`
`T->lChild = p->lChild;`
`T->lChild->rChild = l;`
`T->rChild->lChild = r;`
`}`
`else {`
`if (f->rChild == p) //f的左孩子是p`
`{`
`cout << "LR调整" << endl;`
`f->rChild = p->lChild->rChild; //将P的左孩子的右孩子提升为新的根节点`
`r = f->rChild->rChild;`
`l = f->rChild->lChild;`
`f->rChild->rChild = p;`
`f->rChild->lChild = p->lChild;`
`f->rChild->lChild->rChild = l;`
`f->rChild->rChild->lChild = r;`
`}`
`if (f->lChild == p) //f的左孩子是p`
`{`
`cout << "LR调整" << endl;`
`f->lChild = p->lChild->rChild; //将P的左孩子的右孩子提升为新的根节点`
`r = f->lChild->rChild;`
`l = f->lChild->lChild;`
`f->lChild->rChild = p;`
`f->lChild->lChild = p->lChild;`
`f->lChild->lChild->rChild = l;`
`f->lChild->rChild->lChild = r;`
`}`
`}`
`}`
`//RL调整`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::RLAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f)
{
Node<ElementType>* l, * r;`
`if (T == p) //->balanceFctor==-2&&T->rChild->balanceFctor!=-2`
`{`
`cout << "RL调整" << endl;`
`T = p->rChild->lChild;`
`r = T->rChild;`
`l = T->lChild;`
`T->lChild = p;`
`T->rChild = p->rChild;`
`T->lChild->rChild = l;`
`T->rChild->lChild = r;`
`}`
`else {`
`if (f->rChild == p) //f的左孩子是p`
`{`
`cout << "RL调整" << endl;`
`f->rChild = p->rChild->lChild;`
`r = f->rChild->rChild;`
`l = f->rChild->lChild;`
`f->rChild->lChild = p;`
`f->rChild->rChild = p->rChild;`
`f->rChild->lChild->rChild = l;`
`f->rChild->rChild->lChild = r;`
`}`
`if (f->lChild == p) //f的左孩子是p`
`{`
`cout << "RL调整" << endl;`
`f->lChild = p->rChild->lChild;`
`r = f->lChild->rChild;`
`l = f->lChild->lChild;`
`f->lChild->lChild = p;`
`f->lChild->rChild = p->rChild;`
`f->lChild->lChild->rChild = l;`
`f->lChild->rChild->lChild = r;`
`}`
`}`
`}`
`//RR调整`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::RRAdjust(Node<ElementType>*& T, Node<ElementType>*& p, Node<ElementType>*& f)
{
Node<ElementType>* l;`
`if (T == p) //->balanceFctor==-2&&T->rChild->balanceFctor!=-2`
`{`
`cout << "RR调整" << endl;`
`T = p->rChild; //将P的右孩子提升为新的根节点`
`l = T->lChild;`
`T->lChild = p; //将p降为其右孩子的左孩子`
`p->rChild = l; //将p原来的右孩子的左孩子连接其p的右孩子`
`//注意:p->rChild->balanceFctor==0插入节点时用不上,删除节点时可用`
`}`
`else {`
`if (f->rChild == p) //f的右孩子是p`
`{`
`cout << "RR调整" << endl;`
`f->rChild = p->rChild; //将P的右孩子提升为新的根节点`
`l = f->rChild->lChild;`
`f->rChild->lChild = p; //将p降为其右孩子的左孩子`
`p->rChild = l; //将p原来的右孩子的左孩子连接其p的右孩子`
`}`
`if (f->lChild == p) //f的左孩子是p`
`{`
`cout << "RR调整" << endl;`
`f->lChild = p->rChild; //将P的左孩子提升为新的根节点`
`l = f->lChild->lChild;`
`f->lChild->lChild = p; //将p降为其左孩子的左孩子`
`p->rChild = l; //将p原来的右孩子的左孩子连接其p的右孩子`
`}`
`}`
`}`
`//集成四种调整,并实时更新平衡因子`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::AllAdjust(Node<ElementType>*& T)
{
Node<ElementType>* f = NULL, * p = NULL;`
`factorForTree(T);`
`nodeFctorIsTwoFather(T, f);`
`nodeFctorIsTwo(T, p);`
`while (p)`
`{`
`factorForTree(T);`
`if (p->balanceFctor == 2 && (p->lChild->balanceFctor == 1 || p->lChild->balanceFctor == 0))//LL调整`
`{`
`LLAdjust(T, p, f);`
`factorForTree(T);`
`}`
`else if (p->balanceFctor == 2 && p->lChild->balanceFctor == -1)//LR调整`
`{`
`LRAdjust(T, p, f);`
`factorForTree(T);`
`}`
`else if (p->balanceFctor == -2 && p->rChild->balanceFctor == 1)//RL调整`
`{`
`RLAdjust(T, p, f);`
`factorForTree(T);`
`}`
`else if (p->balanceFctor == -2 && (p->rChild->balanceFctor == -1 || p->rChild->balanceFctor == 0)) //||p->rChild->balanceFctor==0RR调整`
`{`
`RRAdjust(T, p, f);`
`}`
`f = NULL;`
`p = NULL;`
`nodeFctorIsTwoFather(T, f);`
`nodeFctorIsTwo(T, p);`
`}`
`}`
`//先序遍历输出`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::preOrderTraverse(Node<ElementType>* T, int level)`
`{`
`if (T)`
`{`
`cout << "先序" << "(" << T->data << "," << level << ")" << " ";`
`preOrderTraverse(T->lChild, level + 1);`
`preOrderTraverse(T->rChild, level + 1);`
`}`
`}`
`//中序遍历算法`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::inOrderTraverse(Node <ElementType>* T, int level)`
`{`
`if (T)`
`{`
`inOrderTraverse(T->lChild, level + 1); //递归调用先序遍历左子树`
`cout << "中序" << "(" << T->data << "," << level << ")" << " "; //访问根节点`
`inOrderTraverse(T->rChild, level + 1); //递归调用先序遍历右子树`
`}`
`}`
`//二叉树转数组`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::BiTreeToArray(Node <ElementType>* T, ElementType A[], int i, int& count)`
`{`
`if (T != NULL)`
`{`
`A[i] = T->data;`
`if (i > count)`
`count = i;`
`BiTreeToArray(T->lChild, A, 2 * i, count);//左子树下标为根节点下标的两倍`
`BiTreeToArray(T->rChild, A, 2 * i + 1, count);//右子树下标为根节点小标的两倍+1`
`}`
`}`
`//对二叉链表表示的二叉树,按从上到下,从左到右打印结点值,即按层次打印,层次遍历(广度优先搜索)`
`//以数组形式来简化参次遍历,不需要进行递归,但是要求二叉树节点元素不为空的时候进行`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::LevelTraverse(Node <ElementType>* T, ElementType B[], int num)`
`{`
`int n, i, j, t, q, s, p, m = 0, k = 0;`
`n = (int)((log(num) / log(2)) + 1);`
`p = n;`
`for (i = 0; i < n; i++)`
`{`
`k = pow(2, m) + k;`
`t = pow(2, m);`
`j = pow(2, p - 1) - 1;`
`q = pow(2, p) - 1;`
`s = q;`
`for (j; j > 0; j--)`
`{`
`cout << " ";`
`}`
`for (t; t <= k; t++)`
`{`
`if (B[t] == 0)`
`{`
`cout << "*";
for (q; q > 0; q--)
cout << " ";
q = s;
}
else {
cout << B[t];
for (q; q > 0; q--)
cout << " ";
q = s;
}
}
m++;
p--;
j = n - i - 1;
cout << endl;
}
}
//交互创建二叉平衡树
template< class ElementType>
void BalanceBiTree<ElementType>::createSubBalanceBiTree(Node<ElementType>*& T)`
`{`
`int level = 1;`
`int i = 1, j = 0;`
`int A[100] = { 0 };`
`int length = 0;`
`ElementType x;`
`Node<ElementType>* S, * p;`
`T = new Node<ElementType>;`
`T->balanceFctor = 0;`
`T->lChild = NULL;`
`T->rChild = NULL;`
`p = T;`
`cout << "请输入元素(-9999退出):";`
`cin >> x;`
`T->data = x;`
`while (x != -9999)`
`{`
`cout << "请输入元素:";`
`cin >> x;`
`if (x == -9999)`
`return;`
`S = new Node<ElementType>;`
`S->data = x;`
`S->balanceFctor = 0;`
`S->lChild = NULL;`
`S->rChild = NULL;`
`insert(p, S);`
`AllAdjust(T);`
`p = T;`
`inOrderTraverse(T, level);`
`cout << endl;`
`BiTreeToArray(T, A, i, length);`
`cout << "其树状图为:" << endl;`
`LevelTraverse(T, A, length);`
`j = 0;`
`for (j; j < 100; j++)`
`A[j] = 0;`
`level = 1;`
`i = 1;`
`}`
`}`
`//从数组中创建平衡二叉树`
`template< class ElementType>`
`void BalanceBiTree<ElementType>::createBalanceBiTreeFromArray(Node<ElementType>*& T, ElementType A[], int n)
{
Node<ElementType>* S, * p;`
`int i = 1;`
`T = new Node<ElementType>;`
`T->balanceFctor = 0;`
`T->lChild = NULL;`
`T->rChild = NULL;`
`p = T;`
`T->data = A[0];`
`n = n - 1;`
`while (n)`
`{`
`S = new Node<ElementType>;`
`S->data = A[i];`
`S->balanceFctor = 0;`
`S->lChild = NULL;`
`S->rChild = NULL;`
`insert(p, S);`
`AllAdjust(T);`
`p = T;`
`i++;`
`n--;`
`}`
`}`
`//查找元素x`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::search(Node <ElementType>*& T, Node <ElementType>*& p, ElementType x)`
`{`
`if (T)`
`{`
`if (T->data == x)`
`p = T;`
`search(T->lChild, p, x);`
`search(T->rChild, p, x);`
`}`
`}`
`//获取某个元素的父亲指针,不存在返回NULL`
`template<class ElementType>`
`Node <ElementType>* BalanceBiTree<ElementType>::getElementFatherPointer(Node <ElementType>*& T, Node <ElementType>*& f, ElementType x)`
`{`
`if (T)`
`{`
`if (T->lChild != NULL)`
`{`
`if (T->lChild->data == x)`
`f = T;`
`}`
`if (T->rChild != NULL)`
`{`
`if (T->rChild->data == x)`
`f = T;`
`}`
`getElementFatherPointer(T->lChild, f, x);`
`getElementFatherPointer(T->rChild, f, x);`
`}`
`return 0;`
`}`
`//获取前驱元素`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::getPriorElement(Node <ElementType>*& T, ElementType& min, ElementType& max)
{
if (T)
{
min = T->data;
if (min > max)
max = min;
getPriorElement(T->lChild, min, max);
getPriorElement(T->rChild, min, max);
}
}
//获取某个元素的前驱指针
template<class ElementType>
Node <ElementType>* BalanceBiTree<ElementType>::getElementPriorPointer(Node <ElementType>*& T)
{
Node <ElementType>* p;`
`ElementType min = 0, max = -9999;`
`getPriorElement(T, min, max);`
`search(T, p, max);`
`return p;`
`}`
`//获取后继元素`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::getNextElement(Node <ElementType>*& T, ElementType& min, ElementType& max)
{
if (T)
{
max = T->data;
if (min > max)
min = max;
getNextElement(T->lChild, min, max);
getNextElement(T->rChild, min, max);
}
}
//获取某个元素的后继指针
template<class ElementType>
Node <ElementType>* BalanceBiTree<ElementType>::getElementNextPointer(Node <ElementType>*& T)
{
Node <ElementType>* p;`
`ElementType min = 9999, max = 0;`
`getNextElement(T, min, max);`
`search(T, p, min);`
`return p;`
`}`
`//删除叶子节点操作`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::deleteLeafNode(Node <ElementType>*& T, Node <ElementType>*& p, Node <ElementType>*& f)
{
if (p == NULL)
{
cout << "此节点不存在,不能删除" << endl;
return;
}
if (T == p) //根节点即为叶子节点
{
delete p;
T = NULL;
}
else { //删除节点为非根节点的叶子节点
if (f->lChild == p)
{
delete p;
f->lChild = NULL;
}
if (f->rChild == p)
{
delete p;
f->rChild = NULL;
}
}
}
//删除仅有左子树或只有右子树的节点
template<class ElementType>
void BalanceBiTree<ElementType>::deleteOneBranchNode(Node <ElementType>*& T, Node <ElementType>*& p, Node <ElementType>*& f)`
`{`
`if (p == NULL)`
`{`
`cout << "此节点不存在,不能删除" << endl;`
`return;`
`}`
`if (T == p)`
`{`
`if (T->lChild == NULL && T->rChild != NULL)`
`{`
`T = p->rChild;`
`delete p;`
`}`
`if (T->rChild == NULL && T->lChild != NULL)`
`{`
`T = p->lChild;`
`delete p;`
`}`
`}`
`else {`
`if (p->lChild != NULL)`
`{`
`if (f->lChild == p)`
`f->lChild = p->lChild;`
`else`
`f->rChild = p->lChild;`
`}`
`if (p->rChild != NULL)`
`{`
`if (f->lChild == p)`
`f->lChild = p->rChild;`
`else`
`f->rChild = p->rChild;`
`}`
`}`
`}`
`//删除既有左子树又有右子树的节点`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::deleteTwoBranchNode(Node <ElementType>*& T, Node <ElementType>*& p)`
`{`
`Node <ElementType>* f, * next, * prior;`
`if (p == NULL)`
`{`
`cout << "此节点不存在,不能删除" << endl;`
`return;`
`}`
`if (p->balanceFctor == 1) //p的平衡因子为1时,用p的前驱节点代替p`
`{`
`prior = getElementPriorPointer(p->lChild); //获得x的前驱指针`
`if (prior->lChild != NULL && prior->rChild == NULL) //情况一前驱节点只有左孩子`
`{`
`p->data = prior->data;`
`prior->data = prior->lChild->data;`
`delete prior->lChild;`
`prior->lChild = NULL;`
`}`
`if (prior->lChild == NULL && prior->rChild == NULL) //情况二前驱节点为叶子节点`
`{`
`getElementFatherPointer(T, f, prior->data); //得到前驱节点的父节点`
`p->data = prior->data;`
`delete prior;`
`f->rChild = NULL;`
`}`
`}`
`else if (p->balanceFctor == -1) //p的平衡因子为-1时,用p的后继节点代替p`
`{`
`next = getElementNextPointer(p->rChild); //获得x的后继指针`
`cout << next->data;`
`int level = 1;`
`if (next->rChild != NULL && next->lChild == NULL) //情况一后继节点只有右孩子`
`{`
`p->data = next->data;`
`next->data = next->rChild->data;`
`delete next->rChild;`
`next->rChild = NULL;`
`}`
`else if (next->rChild == NULL && next->lChild == NULL) //情况二后继节点为叶子节点`
`{`
`getElementFatherPointer(T, f, next->data); //得到后继节点的父节点`
`p->data = next->data;`
`delete next;`
`f->lChild = NULL;`
`}`
`}`
`else if (p->balanceFctor == 0) //p的平衡因子为0时,用p的前驱或后继节点代替p,这里用前驱`
`{`
`prior = getElementPriorPointer(p->lChild); //获得x的前驱指针`
`if (prior->lChild != NULL && prior->rChild == NULL) //情况一前驱节点只有左孩子`
`{`
`p->data = prior->data;`
`prior->data = prior->lChild->data;`
`delete prior->lChild;`
`prior->lChild = NULL;`
`}`
`if (prior->lChild == NULL && prior->rChild == NULL) //情况二前驱节点为叶子节点`
`{`
`getElementFatherPointer(T, f, prior->data); //得到前驱节点的父节点`
`p->data = prior->data;`
`delete prior;`
`if (p == f) //这块需要特殊记忆,唯独p->balanceFctor==0需要考虑***`
`f->lChild = NULL;`
`else`
`f->rChild = NULL;`
}
}
`}`
`//集成删除的三种情况的操作`
`template<class ElementType>`
`void BalanceBiTree<ElementType>::deleteOperate(Node <ElementType>*& T, ElementType x)
{
Node <ElementType>* f, * p = NULL;`
`search(T, p, x);`
`getElementFatherPointer(T, f, x);`
`if (p == NULL)`
`{`
`cout << "不存在此节点,删除失败!" << endl;`
`return;`
`}`
`if (p->lChild == NULL && p->rChild == NULL) //情况一删除节点为叶子节点`
`{`
`deleteLeafNode(T, p, f);`
`if (T != NULL)`
`AllAdjust(T);`
`}`
`else if ((p->lChild == NULL && p->rChild != NULL) || (p->lChild != NULL && p->rChild == NULL))`
`{`
`deleteOneBranchNode(T, p, f);`
`if (T != NULL)`
`AllAdjust(T);`
`}`
`else //if(p->lChild!=NULL&&p->rChild!=NULL)`
`{`
`deleteTwoBranchNode(T, p);`
`if (T != NULL)`
`AllAdjust(T);`
`}`
`}`
`template<class ElementType>`
`int BinarySearch(ElementType A[], int n, ElementType x)`
`{`
`int mid, low = 0, high = n - 1;`
`while (low <= high)`
`{`
`mid = (low + high) / 2;`
`if (x == A[mid])`
`{`
`return mid;`
`}`
`else if (x < A[mid])`
`{`
`high = mid - 1;`
`}`
`else {`
`low = mid + 1;`
`}`
`}`
`return -1;`
`}`
`//初始化数组`
`void initArray(int A[])`
`{`
`int i = 0;`
`for (i; i < 100; i++)`
`A[i] = 0;`
`}`
`int main()`
`{`
`int x, y;`
`int i = 1;`
`int level = 1;`
`int A[100] = { 0 };`
`int B[100] = { 0 };`
`int length = 0; //存储数组A的有效元素个数`
`Node<int>* root;`
`Node<int>* p;`
`BalanceBiTree<int> T(root);`
`BalanceBiTree<int>::menu();`
`cout << "请输入执行序号:";`
`cin >> x;`
`while (x != 0)`
`{`
`switch (x)`
`{`
`case 1:`
`if (root != NULL)`
`T.destory(root);`
`length = 0;`
`cout << "请输入数组元素的值:";`
`cin >> y;`
`while (y != -9999)`
`{`
`A[length] = y;`
`length++;`
`cout << "请输入数组元素的值:";`
`cin >> y;`
`}`
`cout << "请输入要查询元素的值:";`
`cin >> x;`
`if (BinarySearch(A, length + 1, x) == -1)`
`cout << "不存i=1;在!" << endl;`
`else {`
`cout << "存在,其下标为:" << BinarySearch(A, length + 1, x) << endl;`
`}`
`break;`
`case 2:`
`T.createSubBalanceBiTree(root);`
`break;`
`case 3:`
`cout << "请输入要查询元素的值:";`
`cin >> x;`
`T.search(root, p, x);`
`if (p != NULL)`
`{`
`if (p->data == x)`
`cout << "元素存在!" << endl;`
`else`
`cout << "元素不存在!" << endl;`
`}`
`else {`
`cout << "元素不存在!" << endl;`
`}`
`break;`
`case 4:`
`i = 1;`
`initArray(A);`
`level = 1;`
`cout << "请输入要删除元素的值:";`
`cin >> x;`
`T.deleteOperate(root, x);`
`T.inOrderTraverse(root, level);`
`T.BiTreeToArray(root, A, i, length);`
`cout << "其树状图为:" << endl;`
`T.LevelTraverse(root, A, length);`
`break;`
`case 5:`
`initArray(A);`
`if (root != NULL)`
`T.destory(root);`
`length = 0;`
`y = 1;`
`for (y; y <= 26; y++)`
`{`
`A[length] = y;`
`length++;`
`}`
`T.createBalanceBiTreeFromArray(root, A, length);`
`level = 1;`
`i = 1;`
`T.inOrderTraverse(root, level);`
`cout << endl;`
`initArray(A);`
`T.BiTreeToArray(root, A, i, length);`
`cout << "其树状图为:" << endl;`
`T.LevelTraverse(root, A, length);`
`break;`
`case 6:`
`i = 1;`
`initArray(A);`
`T.AllAdjust(root);`
`T.BiTreeToArray(root, A, i, length);`
`cout << "其树状图为:" << endl;`
`T.LevelTraverse(root, A, length);`
`break;`
`}`
`system("PAUSE");`
`system("CLS");`
`BalanceBiTree<int>::menu();`
`cout << "请输入执行序号:";`
`cin >> x;`
`}`
`if (root != NULL)`
`T.destory(root);`
`return 0;`
`}`
B-树
三、散列表的查找
`
#include<stdio.h>`
`#include<stdlib.h>`
`#include<iostream>`
`#define M 13`
`using namespace std;`
`typedef int ElemType;`
`int kj=0;`
`typedef struct Node {//链表节点的数据结构`
`ElemType data;`
`struct Node* next;`
`}Node,*pNode;`
`typedef struct HashNode {//哈希表每个槽的数据结构`
`pNode first;//指向第一个节点`
`}HashNode,*HashTable;`
`HashTable create_HashTable(int n) {`
`int i;`
`HashTable hashtable = (HashTable)malloc(n * sizeof(HashNode));`
`if (!hashtable) {`
`cout << "哈希表创建失败" << endl;`
`exit(-1);`
`}`
`for (i = 0; i < n; i++) {`
`hashtable[i].first = NULL;//哈希表制空`
`}`
`return hashtable;`
`}`
`//在哈希表中查找数据,哈希函数是key%M`
`//查找成功就返回在链表中的位置`
`//查找失败则返回NULL`
`pNode search_HashTable(HashTable hashtable, ElemType data,int &k) {`
`if (!hashtable)`
`return NULL;`
`pNode pCur = hashtable[data % M].first;`
`while (pCur && pCur->data != data) {`
`k++;`
`pCur = pCur->next;`
`}`
`return pCur;`
`}`
`bool insert_HashTable(HashTable hashtable, ElemType data) {`
`if (search_HashTable(hashtable, data,kj))//如果已经存在,返回false`
`return false;`
`//否则为插入数据分配空间`
`pNode pNew = (pNode)malloc(sizeof(Node));`
`if (!pNew) {`
`cout << "分配数据空间失败"<<endl;`
`exit(-1);`
`}`
`pNew->data = data;`
`pNew->next = NULL;`
pNode pCur = hashtable[data % M].first;
if (!pCur) {//插入位置为第一个位置
hashtable[data % M].first = pNew;
}
else {//只有pCur->next才可以链接pNew
while (pCur->next) {
pCur = pCur->next;
}
pCur->next = pNew;
}
return true;
`}`
`//从哈希表中删除数据`
`//如果data不存在,则返回false`
`//否则,删除并返回true`
`bool delete_HashTable(HashTable hashtable, ElemType data) {`
`if (!search_HashTable(hashtable, data,kj))`
`return false;`
pNode pCur = hashtable[data % M].first;
pNode pPre = pCur;//被删节点的前一个节点,初始值与Cur相同
if (pCur->data == data) {
hashtable[data % M].first = pCur->next;
}
else {
while (pCur && pCur->data != data) {
pPre = pCur;
pCur = pCur->next;
}
pPre->next = pCur->next;
}
free(pCur);
pCur = 0;
return true;
`}`
`void OutHashLink(HashTable hashtable) {`
`for (int i = 0; i < M; i++) {`
`pNode pCur=hashtable[i].first;`
`cout << "关键字为:" << i;`
`while (pCur) {`
`cout << "数据为:" << pCur->data<<" " ;`
`pCur = pCur->next;`
`}`
`cout << endl;`
`}`
`}`
`void destory_HashTable(HashTable hashtable, int n) {`
`int i;`
`for (int i = 0; i < n; i++) {`
`pNode pCur = hashtable[i].first;`
`pNode pDel = NULL;`
`while (pCur) {`
`pDel = pCur;`
`pCur = pCur->next;`
`free(pDel);`
`pDel = 0;`
`}`
`}`
`free(hashtable);`
`hashtable = 0;`
`}`
`int main() {`
`int len = 12;`
`HashTable hashtable;`
`int keys[12] = { 19,14,23,1,68,20,84,27,55,11,10,79 };`
`hashtable = create_HashTable(10);`
`for (int i = 0; i < 12; i++) {`
`insert_HashTable(hashtable, keys[i]);`
`}`
`OutHashLink(hashtable);`
`for (int i = 0; i < 12;i++) {`
`int k = 0;`
`search_HashTable(hashtable, keys[i], k);`
`cout << "比较次数: " << k << "数据为:"<<keys[i]<<endl;`
`}`
`return 0;`
`}`