Algorithm Exercise - Recurrence of Common Search Algorithms

An unknown college student, known as Caigou by Jiang Hu
original author: jacky Li
Email : [email protected]

Time of completion:2023.1.1
Last edited: 2023.1.1

 

Table of contents

Algorithm exercise - reappearance of commonly used search algorithms (PS: 1 -- 3 I wrote it myself, 4 and 5 are too lazy to write, and I took it directly from my classmates)

Pass 1: Sequential Search (Algorithms 7.1 and 7.2)

mission details

related information

programming requirements

Test instruction

Reference Code

Level 2: Binary Search (Algorithm 7.3)

mission details

related information

programming requirements

Test instruction

Reference Code

Level 3: Binary Sorting Trees and Search (Algorithms 7.4-7.7)

mission details

related information

programming requirements

Test instruction

Reference Code

 Level 4: B-tree search and insertion (Algorithms 7.8 and 7.9)

mission details

related information

programming requirements

Test instruction

 Reference Code

Level 5: Hash Table Lookup (Algorithm 7.10)

mission details

related information

programming requirements

Test instruction

Reference Code

The author has something to say


Algorithm exercise - reappearance of commonly used search algorithms (PS: 1 -- 3 I wrote it myself, 4 and 5 are too lazy to write, and I took it directly from my classmates)

Pass 1: Sequential Search (Algorithms 7.1 and 7.2)

mission details

The task of this level: Use the sequential search method to find out the position of the keyword in the list, and the subscript starts counting from 1.

related information

The search process of Sequential Search is: start from one end of the table, and compare the keywords of the records with the given value in turn. If the keyword of a record is equal to the given value, the search is successful; otherwise, if After scanning the entire table, if the record with the key equal to the given value is still not found, the search fails.

Data Element Type Definition

 
 
  1. typedef struct{
  2. KeyType key; //关键字域
  3. InfoType otherinfo; //其他域
  4. }ElemType;

Definition of sequence table

 
 
  1. typedef struct{
  2. ElemType *R; //存储空间基地址
  3. int length; //当前长度
  4. }SSTable;

Algorithm 7.1 Sequential Search

Algorithm Description

Examples are as follows:

  1. int Search_Seq(SSTable ST,KeyType key)
  2. {//在顺序表ST中顺序查找其关键字等于key的数据元素。
  3. //若找到,则函数值为该元素在表中的位置,否则为0
  4. for(i=ST.length;i>=1;--i)
  5. if(ST.R[i].key==key) return i; //从后往前找
  6. return 0;
  7. }

Algorithm 7.1 In each step of the search process, it is necessary to check whether the entire table has been searched, that is, to check whether the loop variable satisfies the condition i>=1 at each step. By improving this program, this detection process can be dispensed with. The improvement method is to find the key assigned to the key before ST.R[0], and here, ST.R[0]it plays the role of a monitoring sentinel, as shown in Algorithm 7.2 .

Algorithm 7.2 Sequential search for setting watch posts

Algorithm Description

  1. int Search_Seq(SSTable ST,KeyType key)
  2. {//在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
  3. ST.R[0].key=key;//“哨兵”
  4. for(i=ST.length;ST.R[i].key!=key;--i);//从后往前找
  5. return i;
  6. }

Analysis of Algorithms

Algorithm 7.2 is only an improvement in programming skills, that is, by setting a monitoring post, it is not necessary to check whether the entire table has been searched at each step in the search process. However, practice has proved that this improvement can reduce the average time required for a search by almost half when the sequential search is ST.length ≥ 1000. Of course, the watch post can also be set at the high subscript. Algorithm 7.2 has the same time complexity as Algorithm 7.1. It has been analyzed in Chapter 2, that is, ASL=n1​∑i=1ni​i=2n+1​ and the time complexity of Algorithm 7.2 is O(n).

programming requirements

According to the prompt, add the code between Begin and End of the editor on the right to complete the task of sequential search.

Test instruction

The platform will test the code you write:

Test input (two lines in total, the first line is the keyword to be searched, and the second line is the order list elements separated by spaces:

4

0 1 2 3 4 5

Expected output:

找到4位置为5

Test input:

7

0 1 2 3 4 5

Expected output:

未找到7

参考代码

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <unordered_map>
#include <unordered_set>

#define IOS std::ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define YES cout << "YES" << endl;
#define yes cout << "yes" << endl;
#define no cout << "no" << endl;
#define NO cout << "NO" << endl;
//#define int long long
#define x first
#define y second
//#define cmp [&](PII a, PII b){ return a.y < b.y; }

const int N = 5e5+10, mod = 1e9+7, M = 1e7+5, K = 1e5+10, Z = 2e5+7;

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

#define MAXSIZE 10000
#define OK 1;

typedef struct{
	int key;//关键字域
}ElemType;

typedef struct{
	ElemType *R;
	int length;
}SSTable;

int InitList_SSTable(SSTable &L)
{
    L.R=new ElemType[MAXSIZE];
	if (!L.R)
	{
		cout<<"初始化错误";
		return 0;
	}
	L.length=0;
	return OK;
}

int Insert_SSTable(SSTable &L) //将所有关键字输入顺序表备查
{
	/***********************Begin**********************/
	int n;
	while(scanf("%d", &n) != EOF)
		L.length ++, L.R[L.length].key = n;
	return OK;
	/*********************** End **********************/
}

int Search_Seq(SSTable ST, int key){
    //在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为
    //该元素在表中的位置,否则为0
    /***********************Begin**********************/
	for(int i = 1; i <= ST.length; i ++)
		if(ST.R[i].key == key)
			return i;
	return 0;
	/*********************** End **********************/
}// Search_Seq

void Show_End(int result,int testkey)
{
	if(result==0)
		cout<<"未找到"<<testkey<<endl;
	else
		cout<<"找到"<<testkey<<"位置为"<<result<<endl;
	return;
}
int main()
{
	int testkey1;
    scanf("%d",&testkey1);
    SSTable ST;
	InitList_SSTable(ST);
	Insert_SSTable(ST);
	int result;
	result=Search_Seq(ST, testkey1);
	Show_End(result,testkey1);
}

Level 2: Binary Search (Algorithm 7.3)

mission details

The task of this level: use the binary search algorithm to find the position of the keyword in the ordered list, and the subscript starts counting from 1.

related information

Binary Search (Binary Search), also known as binary search, is a more efficient search method. However, the binary search requires that the linear table must adopt a sequential storage structure, and the elements in the table are arranged in order according to the key. In the following and subsequent discussions, it is assumed that ordered lists are in increasing order. The search process of the half search is: starting from the middle record of the table, if the given value is equal to the key of the middle record, the search is successful; if the given value is greater than or less than the key of the middle record, it is greater than or less than Search in the half of the middle record, and repeat the operation until the search is successful, or if the search interval is empty in a certain step, it means that the search fails. Binary search Each search comparison reduces the search range by half. Compared with sequential search, it obviously improves the search efficiency. In order to mark each search interval during the search process, low and high are used to represent the lower and upper bounds of the current search interval respectively, and mid is the middle position of the interval.

Algorithm 7.3 Binary Search

【Algorithm steps】

① Set the initial value of the search interval, low is 1, and high is the table length. ② When low is less than or equal to high, perform the following operations in a loop: The value of mid is the middle value between low and high; Compare the given value key with the key recorded in the middle position, if they are equal, the search is successful, and the middle position is returned mid; ·If they are not equal, use the mid-position record to divide the table pair into front and back sub-tables. If the key is smaller than the keyword recorded in the middle position, high is taken as mid-1, otherwise low is taken as mid+1. ③ The loop ends, indicating that the search interval is empty, and the search fails, and 0 is returned. .

【Algorithm Description】

  1. int Search_Bin(SSTable ST,KeyType key)
  2. {//在有序表ST中折半查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
  3. low=1;high=ST.length; //置查找区间初值
  4. while(low<=high)
  5. {
  6. mid=(low+high)/2;
  7. if(key==ST.R[mid].key) return mid; //找到待查元素
  8. else if(key<ST.R[mid].key) high=mid-1; //继续在前一子表进行查找
  9. else low=mid+1; //继续在后一子表进行查找
  10. } //while
  11. return 0; //表中不存在待查元素
  12. }

This algorithm is easy to understand. The only thing to note is that the condition for loop execution is low<=high, not low<high, because when low=high, there is still the last node in the search interval, and further comparison is required. The average search length of the half search algorithm 7.3 is ASL=nn+1​log2​(n+1)−1 When n is large, the time complexity has approximate results O(log2​n).

programming requirements

According to the prompt, add the code between Begin and End of the editor on the right to complete the task of searching in half.

Test instruction

The platform will test the code you write:

Test input (two lines in total, the first line is the keyword to be searched, and the second line is the order list elements separated by spaces:

4

0 1 2 3 4 5

Expected output:

找到4位置为5

Test input:

7

0 1 2 3 4 5

Expected output:

未找到7

Reference Code

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <unordered_map>
#include <unordered_set>

#define IOS std::ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define YES cout << "YES" << endl;
#define yes cout << "yes" << endl;
#define no cout << "no" << endl;
#define NO cout << "NO" << endl;
//#define int long long
#define x first
#define y second
//#define cmp [&](PII a, PII b){ return a.y < b.y; }

const int N = 5e5+10, mod = 1e9+7, M = 1e7+5, K = 1e5+10, Z = 2e5+7;

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

#define ERROR 0
#define MAXSIZE 2000
#define OK 1;

typedef struct{
	int key;//关键字域
}ElemType;

typedef struct{
	ElemType *R;
	int length;
}SSTable;

int InitList_SSTable(SSTable &L)
{
	L.R=new ElemType[MAXSIZE];
	if (!L.R)
	{
		cout<<"初始化错误";
		return 0;
	}
	L.length=0;
	return OK;
}

int Insert_SSTable(SSTable &L) //将所有关键字输入顺序表备查
{
/***********************Begin**********************/
	int n;
	while(scanf("%d", &n) != EOF)
		L.length ++, L.R[L.length].key = n;
	return OK;
/*********************** End **********************/
}

int Search_Bin(SSTable ST,int key) {
   // 在有序表ST中折半查找其关键字等于key的数据元素。若找到,则函数值为
   // 该元素在表中的位置,否则为0
/***********************Begin**********************/
	int low = 1, high = ST.length;
	while(low <= high)
	{
		int mid = (low + high) >> 1;
		if(ST.R[mid].key == key) return mid;
		else if(key > ST.R[mid].key) low = mid + 1;
		else high = mid - 1;
	}  
	return ERROR;
/*********************** End **********************/
}// Search_Bin

void Show_End(int result,int testkey)
{
	if(result==0)
		cout<<"未找到"<<testkey<<endl;
	else
		cout<<"找到"<<testkey<<"位置为"<<result<<endl;
	return;
}

int main()
{
	int testkey1;
    scanf("%d",&testkey1);
    SSTable ST;
	InitList_SSTable(ST);
	Insert_SSTable(ST);
	int result;
	result=Search_Bin(ST, testkey1);
	Show_End(result,testkey1);
}

Level 3: Binary Sorting Trees and Search (Algorithms 7.4-7.7)

mission details

The task of this level: realize the creation, insertion, search, and deletion operations of the binary sorting tree.

related information

Binary Sort Tree (Binary Sort Tree), also known as binary search tree, is a special binary tree that is useful for sorting and searching. 1. Definition of Binary Sorted Tree A binary sorted tree is either an empty tree, or a binary tree with the following properties: (1) If its left subtree is not empty, the values ​​of all nodes on the left subtree are smaller than it (2) If its right subtree is not empty, the values ​​of all nodes on the right subtree are greater than the value of its root node; (3) Its left and right subtrees are also are binary sorted trees. A binary sort tree is defined recursively. An important property of the binary sorting tree can be drawn from the definition: when traversing a binary tree in order, an ordered sequence with increasing node values ​​can be obtained.

programming requirements

According to the prompt, add the code between Begin and End of the editor on the right to complete the task of searching in half.

Test instruction

The platform will test the code you write. The following are two examples of test cases.

Test input (3 lines in total: the first line is the character sequence for constructing the binary sorting tree, and the end of the line is the end symbol; the second line is a single character, which is the character that needs to be #searched in the binary sorting tree; the third line is a single character, is the character that needs to be removed from the binary sort tree):

Reference Code

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <unordered_map>
#include <unordered_set>

#define IOS std::ios::sync_with_stdio(false)
#define inf 0x3f3f3f3f
#define YES cout << "YES" << endl;
#define yes cout << "yes" << endl;
#define no cout << "no" << endl;
#define NO cout << "NO" << endl;
//#define int long long
#define x first
#define y second
//#define cmp [&](PII a, PII b){ return a.y < b.y; }

const int N = 5e5+10, mod = 1e9+7, M = 1e7+5, K = 1e5+10, Z = 2e5+7;

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

#define ENDFLAG '#'
typedef struct ElemType{	
	char key;
}ElemType;

typedef struct BSTNode{
	ElemType data;	//结点数据域
	BSTNode *lchild,*rchild;	//左右孩子指针
}BSTNode,*BSTree;


//算法7.4 二叉排序树的递归查找
BSTree SearchBST(BSTree T,char key) {
  //在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
  //若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
/***********************Begin**********************/
	if(!T || key == T -> data.key) return T;
	else if (key < T -> data.key)  return SearchBST(T -> lchild, key);
	else return SearchBST(T -> rchild, key);  
/*********************** End **********************/
} // SearchBST



//算法7.5 二叉排序树的插入
void InsertBST(BSTree &T,ElemType e ) {
  //当二叉排序树T中不存在关键字等于e.key的数据元素时,则插入该元素
/***********************Begin**********************/
	if(!T) 
	{                				
		BSTree S = new BSTNode; 
        S -> data = e, S -> lchild = S -> rchild = NULL, T = S;
	}
	else if (e.key < T -> data.key) InsertBST(T -> lchild, e);	
	else if (e.key > T -> data.key) InsertBST(T -> rchild, e);	
/*********************** End **********************/
}// InsertBST



//算法7.6 二叉排序树的创建
void CreateBST(BSTree &T ) {
  //依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
/***********************Begin**********************/
	T=NULL; ElemType e; cin >> e.key;
	while(e.key != ENDFLAG)
	{
    	InsertBST(T, e);
    	cin >> e.key;			
	}   
/*********************** End **********************/
}//CreatBST

void DeleteBST(BSTree &T,char key) {
  //从二叉排序树T中删除关键字等于key的结点
/***********************Begin**********************/
	BSTree p = T, f = NULL, q, s;      //初始化

  /*------------下面的while循环从根开始查找关键字等于key的结点*p-------------*/
  while(p)
  {                  
	if(p -> data.key == key) break;  	      	//找到关键字等于key的结点*p,结束循环
	f = p;                                			//*f为*p的双亲结点
	if(p -> data.key > key)  p = p -> lchild;     	//在*p的左子树中继续查找
	else p = p -> rchild;  	                  		//在*p的右子树中继续查找
	}
	if(!p) return;                         		//找不到被删结点则返回

/*―考虑三种情况实现p所指子树内部的处理:*p左右子树均不空、无右子树、无左子树―*/
	if((p -> lchild) && (p -> rchild)) 
	{     		//被删结点*p左右子树均不空
		q = p, s = p->lchild;
		while(s -> rchild)                			//在*p的左子树中继续查找其前驱结点,即最右下结点
			q = s, s = s -> rchild;	         		//向右到尽头
		p -> data = s -> data;               			//s指向被删结点的“前驱”
		if(q != p)
			q -> rchild = s->lchild;     	//重接*q的右子树
		else q -> lchild = s -> lchild;        		//重接*q的左子树
		delete s;
	}//if
	else
	{
		if(!p->rchild)               		//被删结点*p无右子树,只需重接其左子树
			q = p, p = p -> lchild; 
		else if(! p -> lchild)               		//被删结点*p无左子树,只需重接其右子树
			q = p, p = p -> rchild;
	/*――――――――――将p所指的子树挂接到其双亲结点*f相应的位置――――――――*/
		if(!f) T = p;                       			//被删结点为根结点
		else if (q == f -> lchild) f -> lchild = p;   	//挂接到*f的左子树位置
		else f -> rchild = p;                 		//挂接到*f的右子树位置
		delete q;
	}
/*********************** End **********************/
}//DeleteBST

//算法 7.7 二叉排序树的删除

//中序遍历
void InOrderTraverse(BSTree &T)
{
/***********************Begin**********************/
	if(T)
	{
		InOrderTraverse(T -> lchild);
		cout << T->data.key;
		InOrderTraverse(T -> rchild);
	}	
/*********************** End **********************/
}

int main()
{
	BSTree T;
	CreateBST(T);
	cout<<"当前有序二叉树中序遍历结果为";
	InOrderTraverse(T);
    cout<<endl;
	char key;//待查找或待删除内容
	cin>>key;
	BSTree result=SearchBST(T,key);
	if(result)
	{cout<<"找到字符"<<key<<endl;}
	else
	{cout<<"未找到"<<key<<endl;}
	cin>>key;
	DeleteBST(T,key);
	cout<<"当前有序二叉树中序遍历结果为";
	InOrderTraverse(T);
}

 Level 4: B-tree search and insertion (Algorithms 7.8 and 7.9)

mission details

The task of this level: complete the construction, search and insertion of the B-tree according to the given data.

related information

The search methods described above are applicable to smaller files stored in the computer memory, collectively referred to as the internal search method. If the file is very large and stored in external memory for searching, these searching methods are not applicable. The internal search methods all search in units of nodes, which requires repeated internal and external memory exchanges, which is very time-consuming. In 1970, R.Bayer and E.Mccreight proposed a balanced multi-fork tree suitable for external search - B-tree, directory management in the disk management system, and most of the index organizations in the database system use B-tree This data structure.

B-tree search

The process of searching on a B-tree is similar to that of a binary sorted tree. For example, on the B-tree shown in the figure below

*aThe process of searching for keyword 47 is as follows: first, start from the root, and find the node according to the root node pointer t , because *athere is only one keyword in the node, and 47>35, if the searched record exists, it must be pointed by the pointer P1 In the subtree of , find *cthe node along the pointer, the node has two keywords (43 and 78), and 43<47<78, if the searched record exists, it must be in the subtree pointed to by the pointer P1. Similarly, the node is found along the pointer *g, the node is searched sequentially, and the keyword 47 is found, thus, the search is successful. The process for unsuccessful lookups is similar, for example, lookup 23 in the same tree. *bStarting from the root, because 23<35, find the node along the pointer P0 in the node , and because there is only one keyword 18 in the node, and 23>18, find the node *balong the second pointer P1 in the node *e. Similarly, because 23<27, search down the pointer. At this time, because the pointer points to a leaf node, it means that the keyword 23 does not exist in this B-tree, and the search ends due to failure. It can be seen that the process of searching on the B-tree is a process of looking up the node along the pointer and searching for the key of the node. Since the B-tree is mainly used as a file index, its search involves the access of external storage, and the reading and writing of external storage is omitted here, and only a schematic description is given. Suppose the node type is defined as follows:

  1. #define m 3 // B-树的阶,暂设为3
  2. typedef struct BTNode
  3. {
  4. int keynum;//结点中关键字的个数,即结点的大小
  5. struct BTNode *parent; //指向双亲结点
  6. KeyType K[m+1];//关键字向量,0号单元未用
  7. struct BTNode *ptr[m+1];//子树指针向量
  8. Record *recptr[m+1]; //记录指针向量,0号单元未用
  9. }BTNode,*BTree; //B-树结点和B-树的类型
  10. typedef struct
  11. {
  12. BTNode *pt; //指向找到的结点
  13. int i; //1..m,在结点中的关键字序号
  14. int tag; //1:查找成功,0:查找失败
  15. }Result; //B-树的查找结果类型

Algorithm 7.8 B-Tree Search

[Algorithm steps] Compare the given value key with each key K1, K2, ..., Kj (1≤j≤m−1) of the root node. Since the key sequence is ordered, it can be searched Sequential search can also be used to search in half. When searching: ① If key=Ki (1≤i≤j), the search is successful; ② If key<K1, continue searching down the subtree pointed to by the pointer P0; ③ If Ki<key<Ki+1 (1≤i≤j−1), then continue to search down along the subtree pointed to by the pointer Pi; ④ If key>Kj, continue to search down along the subtree pointed to by the pointer Pj. If the keyword whose value is key is found in the top-down search process, the search is successful; if it is not found until the leaf node, the search fails.

B-tree insertion

B-tree is a dynamic search tree, so its generation process starts from an empty tree and is obtained by inserting keywords one by one during the search process. However, since the number of keywords in all non-terminal nodes in the B-tree except the root must be greater than or equal to ⌈m/2⌉, inserting a keyword each time does not add a leaf node to the tree, but First, add a keyword to a non-terminal node at the lowest level. If the number of keywords in the node does not exceed m−1, the insertion is completed. Otherwise, it indicates that the node is full, and the "split" of the node is generated. ", divide this node into two nodes on the same layer. In general, the node splitting method is: divide the node into two with the intermediate keyword as the boundary, and then insert the intermediate keyword upwards into the parent node. If the parent node is full, Continue to decompose in the same way. In the worst case, it has been decomposed to the root node of the tree, and the height of the B-tree is increased by 1 at this time.

Algorithm 7.9 B-Tree Insertion

[Algorithm steps] ① Search the record of the given keyword in the B-tree. If the search is successful, the insertion operation will fail; otherwise, insert the new record as a null pointer ap into the upper layer node of the leaf node that failed to find ( pointed to by q). ② If after inserting the new record and the null pointer, the number of keywords of the node pointed to by q does not exceed m−1, the insertion operation is successful, otherwise, go to step ③. ③ Take the ⌈m/2⌉th keyword K⌈m/2⌉​of the node as the split point, and divide the node into 3 parts: K⌈m/2⌉​left part, K⌈m/ 2⌉​, K⌈m/2⌉​right part. The left part of K⌈m/2⌉ remains in the original node; the right part of K⌈m/2⌉ is stored in a newly created node (pointed to by ap); the key value is K⌈m/2⌉ ​The record and pointer ap are inserted into the parent node of q. Because a new record is added to the parent node of q, the operations of ② and ③ must be repeated for the parent node of q, and so on, until the node pointed to by q is the root node, and then go to step ④. ④ Since the root node has no parents, the pointers ap and q of the two nodes generated by its split, and the record whose key word is [illustration] constitute a new root node. At this point, the height of B- increases by 1.

programming requirements

According to the prompt, complete the codes of the insert function InsertBTree and the search function SearchBTree of the B-tree in the editor on the right to complete the construction of the B-tree for the given array of the main function.

Test instruction

The platform will test the code you write:

test input: None;

Expected output:

OK

 Reference Code

//算法7.8 B-树的查找
//算法7.9 B-树的插入
#include<iostream>
using namespace std;
#define FALSE 0
#define TRUE 1
#define OK 1
#define m 3						//B-树的阶,暂设为3
typedef struct BTNode{
	int keynum;					//结点中关键字的个数,即结点的大小
	BTNode *parent;				//指向双亲结点
	int key[m+1];				//关键字矢量,0号单元未用
	BTNode *ptr[m+1];			//子树指针矢量
}BTNode,*BTree;

//- - - - - B-树的查找结果类型定义- - - - -
struct Result{
  BTNode *pt;     							//指向找到的结点
  int i;           							//1..m,在结点中的关键字序号
  int tag;         							//1:查找成功,0:查找失败
}; 	                           


int Search(BTree T,int key)
{
	BTree p=T;	
	int endnum;
	if(p)						//树不为空时
	{
		endnum=p->keynum;		//获得首节点包含的记录个数
	}
	else
	{
		return 0;				//返回没找到
	}
	int i=0;
	if(endnum==0)
	{
		return i;				//树存在,但仅有一个为空根节点
	}
	else if(key>=p->key[endnum])//节点不为空,但当前值比最大的key还大
	{
		i=endnum;
		return i;
	}
	else if(key<=p->key[1])		//节点不为空,但当前值比最小的key还小
	{
		return i;}
	else
	{
		for(i=1;i<endnum;i++)	//有合适的位置,即处于当前结点的最大和最小值之间,或找到了
		{
			if(p->key[i]<=key && key<p->key[i+1])
				return i;
		}
	}
}

void Insert(BTree &q,int i,int x,BTree &ap)
{//将x插入q结点的i+1位置中
	int j;
	for(j=m-1;j>i;j--)			
	{
		//将插入位置之后的key全部后移一位
		q->key[j+1]=q->key[j];
	}
	for(j=m;j>i;j--)
	{
		//相应地也移动其后ptr的位置
		q->ptr[j]=q->ptr[j-1];
	}
	q->key[i+1]=x;//插入x到该位置
	q->ptr[i+1]=ap;
	q->keynum++;
}

void split(BTree &q,int s,BTree &ap)
{	//将q->key[s+1,..,m], q->ptr[s+1,..,m]移入新结点*ap作为右结点
	//原结点作为新的左侧结点
	//中间值被保存在ap[0]->key中,等待找到跳转回InsertBTree()寻找到到合适的插入位置插入	
	int i;
	ap=new BTNode;
	for(i=s+1;i<=m;i++)
	{	//将q->key[s+1,..,m]保存到ap->key[0,..,m-s+1]中
		//将q->ptr[s+1,..,m]保存到ap->ptr[0,..,m-s+1]中
		ap->key[i-s-1]=q->key[i];	
		ap->ptr[i-s-1]=q->ptr[i];
	}
	if(ap->ptr[0])
	{
		//当ap有子树的时候
		for(i=0;i<=1;i++)
		{
			//将ap的子树的父亲改为ap自己
			ap->ptr[i]->parent=ap;
		}
	}
	ap->keynum=(m-s)-1;
	ap->parent=q->parent;//将ap的父亲改为q的父亲
	q->keynum=q->keynum-(m-s);//修改q的记录个数
}

void NewRoot(BTree &T,BTree q,int x,BTree &ap)//生成含信息(T, x, ap)的新的根结点*T,原T和ap为子树指针
{
	BTree newT=new BTNode;//新建一个结点作为新的根
	
	newT->key[1]=x;//写入新根的key[1]
	newT->ptr[0]=T;//将原来的树根作为新根的左子树
	newT->ptr[1]=ap;//ap作为新根的右子树
	newT->keynum=1;
	newT->parent=NULL;//新根的父亲为空

	ap->parent=newT;//ap的父亲为新根
	T->parent=newT;//T的父亲为新根

	T=newT;//树改成新根引导的
}

//算法7.9 B-树的插入
int InsertBTree(BTree &T,int K,BTree q,int i){
/***********************Begin**********************/



/*********************** End **********************/
}							//InsertBTree

//算法7.8 B-树的查找
Result SearchBTree(BTree &T, int key){
/***********************Begin**********************/



/*********************** End **********************/
}//SearchBTree

void InitialBTree(BTree &T)
{
	//初始化一个空的根
	T->keynum=0;		
	T->parent=NULL;	
	for(int i=0;i<m+1;i++)
	{
		T->ptr[i]=NULL;
	}
}

int main()
{
	BTree T=new BTNode;
	InitialBTree(T);
	//先用SearchBTree()找到要插入的位置,得到一个Result结构体
	//再用InsertBTree()插入数据
	Result result;
	int a[11]={45,24,53,90,3,12,50,61,70,100};
	for(int i=0;i<10;i++)
	{
		result=SearchBTree(T,a[i]);
		if(result.tag==0)
		{
			InsertBTree(T,a[i],result.pt,result.i);
		}
	}
	cout<<"OK";
}

Level 5: Hash Table Lookup (Algorithm 7.10)

mission details

The task of this level: use the hash table search method to find out the position of the keyword in the list, and the subscript starts counting from 1.

related information

The search methods based on the linear table and tree table structure discussed above are all based on the comparison of keywords. In the search process, only the relative size between the keys of each element is considered. The position of the record in the storage structure is not directly related to its key. The search time is related to the length of the table, especially when there are many nodes. When searching, a large number of keywords of invalid nodes must be compared, resulting in a very slow search speed. If a direct relationship can be established between the storage location of an element and its keyword, then when searching, there is no need to compare or do few comparisons, and the corresponding record can be directly found by the keyword according to this relationship. This is the idea of ​​the hash search method (Hash Search), which directly calculates the address of the element by performing a certain operation on the keyword value of the element, that is, uses the direct conversion method from the keyword to the address without repeated comparisons. Therefore, the hash lookup method is also called hash method or hash method. Several commonly used terms: (1) Hash function and hash address : establish a definite correspondence H between the storage location p of the record and its keyword key, so that p=H(key), this correspondence is called H is a hash function, and p is a hash address. (2) Hash table : A limited and continuous address space used to store data records whose corresponding hash addresses are calculated according to the hash function. Usually the storage space of the hash table is a one-dimensional array, and the hash address is the subscript of the array. (3) Conflicts and synonyms : The same hash address may be obtained for different keywords, that is, key1≠key2, and H(key1)=H(key2), this phenomenon is called conflict. Keywords with the same function value are called synonyms for the hash function, and key1 and key2 are called synonyms for each other. Common methods for constructing hash functions include number analysis , square-centering , folding , and division-and-remainder . The means of dealing with conflicts mainly include open address method andThere are two types of chain address methods . Taking the open address method as an example, the storage representation of the hash table is given below.

  1. //- - - - -开放地址法散列表的存储表示- - - - -
  2. #define m 20 //散列表的表长
  3. typedef struct{
  4. KeyType key; //关键字项
  5. InfoType otherinfo; //其他数据项
  6. }HashTable[m];

Algorithm steps

The process of searching on a hash table is basically the same as the process of creating a hash table. Algorithm 7.10 describes the lookup process of the open address method (linear detection method) to deal with the collision of the hash table.

Algorithm 7.10 Lookup in a Hash Table

① Given the keyword key to be searched, calculate H0=H(key) according to the hash function set when creating the table. ② If the unit H0 is empty, the checked element does not exist. ③ If the keyword of the element in unit H0 is key, the search is successful. ④ Otherwise, repeat the following conflict resolution process: · Calculate the next hash address Hi according to the method of conflict resolution; · If the unit Hi is empty, the element to be checked does not exist; , the search is successful.

Algorithm Description

Examples are as follows:

  1. #define NULLKEY 0 //单元为空的标记
  2. int SearchHash(HashTable HT,KeyType key)
  3. {//在散列表HT中查找关键字为key的元素,若查找成功,返回散列表的单元标号,否则返回-1
  4. H0=H(key);
  5. //根据散列函数H(key)计算散列地址
  6. if(HT[H0].key==NULLKEY) return -1; //若单元H0为空,则所查元素不存在
  7. else if(HT[H0].key==key) return H0; //若单元H0中元素的关键字为key,则查找成功
  8. else
  9. {
  10. for(i=1;i<m;++i){
  11. Hi=(H0+i)%m; //按照线性探测法计算下一个散列地址Hi
  12. if(HT[Hi].key==NULLKEY) return -1; //若单元Hi为空,则所查元素不存在
  13. else if(HT[Hi].key==key) return Hi; //若单元Hi中元素的关键字为key,则查找成功
  14. } //for
  15. return -1;
  16. } //else
  17. }

Analysis of Algorithms

It can be seen from the search process of the hash table: (1) Although the hash table has established a direct image between the key and the storage location of the record, due to the occurrence of "conflict", the search process of the hash table is still a given value and The process by which keywords are compared. Therefore, it is still necessary to use the average lookup length as a measure of the lookup efficiency of the hash table. (2) The number of keywords that need to be compared with a given value in the search process depends on three factors: the hash function, the method of dealing with conflicts, and the filling factor of the hash table. The filling factor α of the hash table is defined as α = the length of the hash table, the number of records filled in the table​ α marks the fullness of the hash table. Intuitively, the smaller α is, the less possibility of conflict occurs; on the contrary, the larger α is, the more records have been filled in the table, and the possibility of conflict is greater when refilling records. , the greater the number of keywords a given value needs to be compared against. (3) The "good or bad" of the hash function first affects the frequency of conflicts. However, it is generally believed that any "uniform" hash function has the same possibility of conflict for the same group of random keywords. If the set hash function is "uniform", it will affect the average search length. There are only two factors - the method of dealing with conflicts and the fill factor α. 4) It can be seen from Table 7.3 that the average search length of the hash table is a function of α, not a function of the number of records n. Therefore, when designing a hash table, no matter how large n is, an appropriate α can always be selected so as to limit the average search length within a range.

programming requirements

According to the prompt, add the code between Begin and End of the editor on the right to complete the task of hash table lookup.

Test instruction

The platform will test the code you write:

Test input (two lines in total, the first line is the keyword to be searched, and the second line is the elements in the hash table separated by spaces:

55

-1 14 1 68 27 55 19 20 84 79 23 11 10 -1 -1 -1

Expected output:

在第5位置找到

Test input:

47

-1 14 1 68 27 55 19 20 84 79 23 11 10 -1 -1 -1

Expected output:

未找到

参考代码

#include<iostream>
#include<stdio.h>
using namespace std;

//算法7.10 哈希表的查找
//- - - - -开放地址法哈希表的存储表示- - - - -
#define m 16                        			//哈希表的表长
#define NULLKEY 0                 			//单元为空的标记

struct HashTable{
   int  key;		         	 			//关键字项
// InfoType  otherinfo;					//其他数据项
};

//	算法7.10为哈希表查找的算法,采用线性探测法处理冲突。
//	【算法实现】

int H(int key)
{
	int result;
	result=key%13;
	return result;
} 

int SearchHash(HashTable HT[],int key){
  //在哈希表HT中查找关键字为key的元素,若查找成功,返回哈希表的单元标号,否则返回-1 
  /***********************Begin**********************/
  for(int i=1;i<=m;i++)
  {
  	if(HT[i].key==key)
  	  return i;
  }

return -1;
  
  /*********************** End **********************/
}//SearchHash

int main()
{	
	int result,i=0;
	int a[m];
	char end=' ';
	int lookfor;		//lookfor为待查找的元素 
	scanf("%d",&lookfor);
	for(;i<m;i++)
	{
		scanf("%d",&a[i]);
	}
	HashTable HT[m];
	for(i=0;i<16;i++)
	{
		HT[i].key=a[i];
	}
	result=SearchHash(HT,lookfor);
	if(result!=-1)
	{
		cout<<"在第"<<result<<"位置找到"<<endl;
	}
	else
	{
		cout<<"未找到"<<endl;
	}
}

The author has something to say

If you feel that what the blogger said is useful to you, please click to support it, and will continue to update such issues...

Guess you like

Origin blog.csdn.net/weixin_62075168/article/details/128513547