数据结构实现—查找的平均效率比较(CC++)

数据结构实现—查找的平均效率比较(C/C++)

在这里插入图片描述

顺序查找和折半查找

#include<iostream>
#include<time.h>
#include<algorithm>
using namespace std;
const int MAX = 10000,maxn=100000;//注意MAX改变时平均查找长度也会因为相同随机数的生成概率改变而有所变化
//但是相同MAX下查找的平均长度相差不大,maxn代表查找次数,查找次数越多,结果越准确
int n;
int nums[MAX];
int sample_find(int x)
{
	for (int i = 0; i < n; i++)
		if (x == i)
			return i + 1;
	return 0;
}
void sample()//顺序查找在数据量为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了
}
int bin_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;
		else if (nums[mid] > x)
			time+=1,r = mid;
		else
			time+=2,l = mid+1;//注意else和else if实际上也进行了比较,这里也要算入查找长度
	}
	return time;
}
void bin()
{
	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我们会发现,当数据量较小时,顺序的效率可能会比折半高,因为折半每次更新下一次查询的区间时产生的平均比较次数更多

int main()
{
	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();
	return 0;
}

散列查找

#include<iostream>
#include<string>
#include <cstdio>
#include <cstdlib>
#include <cstdbool>
#include<time.h>
#define HASHSIZE 10000	//定义散列表长为数组的长度
using namespace std;
//首先定义相关的结构体
int n;
int keys[HASHSIZE];
const int maxn = 100000;
typedef struct HNode {
	int key;
	HNode* next;
}Hnode;
/*
	创建哈希表
		heahLink哈希表,里面存储的为指针变量
		key关键字列表
		n关键字数目
*/
void createHB(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为要查找的关键字
*/
void search_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
//但是相对来说散列表的查找不是很稳定,因为它依靠数据本身的值来创建表。
/*
	释放内存空间
*/
void FreeNode(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);
	}
}
void print(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);
	}
}
void Hash(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);
}
int main() {
	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);//释放动态内存
	return 0;
}

二叉排序树查找

#include <stdio.h>
#include <stdlib.h>
#include<iostream>
using namespace std;
const int MAX = 100000, maxn = 100000;
int n;
int nums[MAX];
typedef int KeyType;
typedef struct  node
{
    KeyType  key; /*关键字的值*/
    struct node* lchild, * rchild;/*左右指针*/
}BSTNode, * BSTree;
void InsertBST(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;
    }
    else
        if (key < (*bst)->key)
            InsertBST(&((*bst)->lchild), key);/*将s插入左子树*/
        else
            if (key > (*bst)->key)
                InsertBST(&((*bst)->rchild), key); /*将s插入右子树*/
}
void  CreateBST(BSTree* bst,KeyType key)
/*从键盘输入元素的值,创建相应的二叉排序树*/
{
    *bst = NULL;
      InsertBST(bst, key);
}
void  PreOrder(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;  /*在右子树中查找*/
    }
    return NULL; /*查找失败*/
}/*SearchBST*/
void BST(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);
}//和散列表有点类似,二叉排序树可能退化成一个链表,从而导致效率低下
int main()
{
    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]);
        else
            CreateBST(&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);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值