#include<iostream>#include<time.h>#include<algorithm>usingnamespace std;constint MAX =10000,maxn=100000;//注意MAX改变时平均查找长度也会因为相同随机数的生成概率改变而有所变化//但是相同MAX下查找的平均长度相差不大,maxn代表查找次数,查找次数越多,结果越准确int n;int nums[MAX];intsample_find(int x){for(int i =0; i < n; i++)if(x == i)return i +1;return0;}voidsample()//顺序查找在数据量为MAX时的平均查找长度{int x, t = maxn;double sum =0;for(int i =0; i < t; i++){
x =rand();
sum +=sample_find(x);}printf("顺序查找平均查找长度:%lfn\n", sum / maxn / n);//总查找长度先除以查找次数再除以n的长度就可以知道平均是多少n了}intbin_find(int x)//折半查找{int l =0, r = n;int mid, time =0;//time是比较次数,用来代表查找长度while(l < r){
mid =(l + r)/2;
time++;if(nums[mid]== x)break;elseif(nums[mid]> x)
time+=1,r = mid;else
time+=2,l = mid+1;//注意else和else if实际上也进行了比较,这里也要算入查找长度}return time;}voidbin(){int x, t = maxn;double sum =0;for(int i =0; i < t; i++){
x =rand();
sum +=bin_find(x);}printf("折半查找平均查找长度:%lfn\n", sum / maxn / n);}//改变maxn我们会发现,当数据量较小时,顺序的效率可能会比折半高,因为折半每次更新下一次查询的区间时产生的平均比较次数更多intmain(){srand(time(NULL));
n =rand()% MAX;
n = n >=100? n : n +100;for(int i =0; i < n; i++)
nums[i]=rand();printf("数据个数:%d\n", n);printf("从第1到第%d个分别为:\n",n);for(int i =0; i < n; i++)printf("%d ", nums[i]);putchar('\n');sort(nums, nums + n);//先排序不能在折半中排序,不然两者数据不一样,不能体现出两者真正的性能差距,排序的开销不能算入查找中sample();bin();return0;}
散列查找
#include<iostream>#include<string>#include<cstdio>#include<cstdlib>#include<cstdbool>#include<time.h>#defineHASHSIZE10000//定义散列表长为数组的长度usingnamespace std;//首先定义相关的结构体int n;int keys[HASHSIZE];constint maxn =100000;typedefstructHNode{int key;
HNode* next;}Hnode;/*
创建哈希表
heahLink哈希表,里面存储的为指针变量
key关键字列表
n关键字数目
*/voidcreateHB(Hnode* heahLink[],int key[],int n){for(int i =0; i < n; i++){
Hnode* head =(Hnode*)malloc(sizeof(Hnode));if(!head){printf("error\n");return;}
head->key =0;
head->next =NULL;
heahLink[i]= head;}//插入操作for(int i =0; i < n; i++){
Hnode* p,* H,* s;int j = key[i]% HASHSIZE;
H = p = heahLink[j];while(p->next !=NULL){
p = p->next;}
s =(Hnode*)malloc(sizeof(Hnode));
s->key = key[i];
s->next =NULL;
p->next = s;
H->key++;}}//创建hash表会不断开辟空间,数据量比较大时空间开辟会占用比较多的时间/**
查找某个关键字
heahLink为哈希表
key为要查找的关键字
*/voidsearch_Node(Hnode* hashLink[],int key,double&time){
Hnode* h,* p;
h = p = hashLink[key % HASHSIZE], time++;//直接定位time次数加一while(p->next !=NULL&& p->key != key){
p = p->next;
time++;//链表上进行查找}}//查询效率特别高,但是在数据量较大的情况下拉出来的链比较长,这个时候可以使用一些特殊的查找数来优化,从而效率接近于1//但是相对来说散列表的查找不是很稳定,因为它依靠数据本身的值来创建表。/*
释放内存空间
*/voidFreeNode(Hnode* hashLink[],int n){
Hnode* h,* p;for(int i =0; i < n; i++){
h = p = hashLink[i];while(p->next !=NULL){
p = p->next;free(h);
h = p;}free(h);}}voidprint(Hnode* heahLink[],int n){
Hnode* p;printf("下标 个数\n");//%-d左对齐 %d右对齐for(int i =0; i < n; i++){
p = heahLink[i];printf(" %-2d ", i);//%-d左对齐 %d右对齐while(p->next !=NULL){printf("%-2d ", p->key);
p = p->next;}printf("%-2d \n", p->key);}}voidHash(Hnode* hashLink[]){double time =0;int key;for(int i =0; i < maxn; i++){
key =rand();search_Node(hashLink, key, time);}printf("散列查找(拉链法)平均查找长度:%lfn\n", time / maxn / n);}intmain(){srand(time(NULL));
n =rand()% HASHSIZE;
n = n >=100? n : n +100;for(int i =0; i < n; i++)
keys[i]=rand();printf("数据个数:%d\n", n);printf("从第1到第%d个分别为:\n", n);for(int i =0; i < n; i++)printf("%d ", keys[i]);putchar('\n');
Hnode* hashLink[HASHSIZE];createHB(hashLink, keys, HASHSIZE);//创建拉链法的散列表//print(heahLink, HASHSIZE);Hash(hashLink);FreeNode(hashLink, HASHSIZE);//释放动态内存return0;}
二叉排序树查找
#include<stdio.h>#include<stdlib.h>#include<iostream>usingnamespace std;constint MAX =100000, maxn =100000;int n;int nums[MAX];typedefint KeyType;typedefstructnode{
KeyType key;/*关键字的值*/structnode* lchild,* rchild;/*左右指针*/}BSTNode,* BSTree;voidInsertBST(BSTree* bst, KeyType key)/*若在二叉排序树中不存在关键字等于key的元素,插入该元素*/{
BSTree s;if(*bst ==NULL)/*递归结束条件*/{
s =(BSTree)malloc(sizeof(BSTNode));/*申请新的结点s*/
s->key = key;
s->lchild =NULL;
s->rchild =NULL;*bst = s;}elseif(key <(*bst)->key)InsertBST(&((*bst)->lchild), key);/*将s插入左子树*/elseif(key >(*bst)->key)InsertBST(&((*bst)->rchild), key);/*将s插入右子树*/}voidCreateBST(BSTree* bst,KeyType key)/*从键盘输入元素的值,创建相应的二叉排序树*/{*bst =NULL;InsertBST(bst, key);}voidPreOrder(BSTree root)/*先序遍历二叉树, root为指向二叉树根结点的指针*/{if(root !=NULL){printf("%d ", root->key);/*输出结点*/PreOrder(root->lchild);/*先序遍历左子树*/PreOrder(root->rchild);/*先序遍历右子树*/}}
BSTree SearchBST(BSTree bst, KeyType key,double& time)/*在根指针bst所指二叉排序树bst上,查找关键字等于key的结点,若查找成功,返回指向该元素结点指针,否则返回空指针*/{
BSTree q;
q = bst;while(q){
time++;if(q->key == key)return q;/*查找成功*/if(q->key > key)
time++,q = q->lchild;/*在左子树中查找*/else
time++,q = q->rchild;/*在右子树中查找*/}returnNULL;/*查找失败*/}/*SearchBST*/voidBST(BSTree bst){int key;double time =0;for(int i =0; i < maxn; i++){
key =rand();SearchBST(bst, key, time);}printf("二叉排序树查找平均查找长度:%lfn\n",time / maxn / n);}//和散列表有点类似,二叉排序树可能退化成一个链表,从而导致效率低下intmain(){
BSTree T;int k;srand(time(NULL));
n =rand()% MAX;
n = n >=100? n : n +100;for(int i =0; i < n; i++){
nums[i]=rand();if(i >0)InsertBST(&T, nums[i]);elseCreateBST(&T, nums[i]);}printf("数据个数:%d\n", n);printf("从第1到第%d个分别为:\n", n);for(int i =0; i < n; i++)printf("%d ", nums[i]);putchar('\n');BST(T);return0;}