部分查找算法的对比实现
通过num变量改变数据集的规模,来进行对比。
顺序查找
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include<sys/timeb.h>
typedef int KeyType;
typedef struct {//顺序表结构类型定义
KeyType *R;//表基址
int length;//表长
}SSTable;
int Search_Seq( SSTable ST , KeyType key ){
int i;
ST.R[0] =key;
for( i=ST.length-1; ST.R[i] != key; --i );
return i;
}
int * getRand(int *t,int num){
int *a = (int*)malloc(sizeof(int)*num);
int i;
int temp;
srand(time(NULL));
for(i = 0;i<num;i++){
temp = rand()%(num+1);
if(i == num/2)
*t = temp;
a[i] = temp;
}
return a;
}
long getTime()
{
struct timeb tb;
ftime(&tb);
//前面是毫秒,后面是微秒
return tb.time*1000+tb.millitm;
}
int main(){
int find;
int num = 1000000;
SSTable s1;
s1.R = getRand(&find,num);
s1.length = num;
long t3 = getTime();
int result1 = Search_Seq(s1,find);
long t4 = getTime();
printf("顺序查找(%d):找到了%d,在下标:%d处,耗时:%ldms",num,find,result1,t4-t3);
return 0;
}
折半查找
#include <stdlib.h>
#include <stdio.h>
#include<time.h>
#include<sys/timeb.h>
typedef int KeyType;
typedef struct {//顺序表结构类型定义
KeyType *R;//表基址
int length;//表长
}SSTable;
int Search_Bin (SSTable ST,KeyType key ) {
int low = 1;
int high = ST.length;//置区间初值
int mid;
while (low <= high) {
mid = (low + high)/ 2;
if (ST.R[mid] == key)
return mid;//找到待查元素
else if (key < ST.R[mid])//缩小查找区间
high=mid-1;//继续在前半区间进行查找
else
low = mid + 1;//继续在后半区间进行查找
}
return 0;//顺序表中不存在待查元素
}
int * getNumber(int *t,int num){
int *a = (int*)malloc(sizeof(int)*num);
int i;
int temp;
a[0] = 0;
srand(time(NULL));
for(i = 1;i<num;i++){
int temp = rand()%(num+1);
if(i == num/2)
*t =i + temp;//递增的
a[i] = i + temp;
}
return a;
}
long getTime()
{
struct timeb tb;
ftime(&tb);
//前面是毫秒,后面是微秒
return tb.time*1000+tb.millitm;
}
int main(){
int find;
int num = 1000000;
SSTable s2;
s2.R = getNumber(&find,num);
s2.length = num;
long t5 = getTime();
int result2 = Search_Bin(s2,find);
long t6 = getTime();
printf("折半查找(%d):找到了%d,在下标:%d,耗时:%dms",num,find,result2,t6-t5);
return 0;
}
二叉排序树
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<sys/timeb.h>
typedef int KeyType; //定义关键字类型
typedef struct node //记录类型
{
KeyType key; //关键字项
struct node *lchild,*rchild; //左右孩子指针
} BSTNode;
BSTNode *CreatBST(KeyType A[],int n); //顺序读入数组A中的关键字, 依序建立一棵二叉排序树并返回根结点指针。由裁判程序实现,细节不表。
int SearchBST(BSTNode *bt,KeyType k); //在函数中输出从根节点出发进行查找的节点路径 ,如果找到k,返回1,否则返回0。
int * getRand(int *t,int num);
long getTime();
int main()
{
int num = 100;
BSTNode *bt = NULL;
int find;
int *arr = getRand(&find,num);
bt = CreatBST(arr,num);
long t1 = getTime();
if(SearchBST(bt,find))
printf("二叉排序树查找(%d)找到了%d,",num,find);
long t2 = getTime();
printf("耗时:%dms",t2-t1);
return 0;
}
// 补充裁判程序未给出函数
int * getRand(int *t,int num){
int *a = (int*)malloc(sizeof(int)*num);
int i;
int temp;
srand(time(NULL));
for(i = 0;i<num;i++){
int temp = rand()%(num+1);
if(i == num/2)
*t = temp;
a[i] = temp;
}
return a;
}
BSTNode * InitBST(KeyType e){
BSTNode *BT;
BT = (BSTNode *)malloc(sizeof(BSTNode));
if(!BT){
return NULL;
}
BT->key = e;
BT->lchild = BT->rchild =NULL;
return BT;
}
// 此处左小于根小于右
void InsertBST(BSTNode * BT, KeyType e){
BSTNode *T;
T = BT;
while(T){
// 寻找插入位置,并插入
if(T->key == e){
return ;
}
if(T->key < e){
// 右孩子存在,则继续寻找
if(T->rchild){
T = T->rchild;
continue;
}
// 不存在则进行插入
T->rchild = (BSTNode *)malloc(sizeof(BSTNode));
T->rchild->key = e;
T->rchild->lchild = T->rchild->rchild =NULL;
return ;
}else if(T->key > e){
// 右孩子存在,则继续寻找
if(T->lchild){
T = T->lchild;
continue;
}
// 不存在则进行插入
T->lchild = (BSTNode *)malloc(sizeof(BSTNode));
T->lchild->key = e;
T->lchild->lchild = T->lchild->rchild =NULL;
}
}
}
BSTNode *CreatBST(KeyType A[],int n){
BSTNode *BT;
int i;
BT = InitBST(A[0]);
for(i=1;i<n;i++){
InsertBST(BT, A[i]);
}
return BT;
}
long getTime()
{
struct timeb tb;
ftime(&tb);
//前面是毫秒,后面是微秒
return tb.time*1000+tb.millitm;
}
int SearchBST(BSTNode *bt,KeyType k){
// 定义
BSTNode *t;
t = bt;
while(t){
// 依次输出查找时的值
//printf("%d ",t->key);
// 如果相等则返回找到
if(t->key==k){
return 1;
}else if(t->key<k){
// 小于根结点则向左孩子寻找
t = t->rchild;
}else{
// 大于根结点则向右孩子寻找
t = t->lchild;
}
}
return 0;
}
散列表
使用的是线性探测法处理冲突,你们可以自己改一改改成拉链法。
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#include<sys/timeb.h>
typedef int ElementType; /* 关键词类型用整型 */
typedef int Index; /* 散列地址类型 */
typedef Index Position; /* 数据所在位置与散列地址是同一类型 */
/* 散列单元状态类型,分别对应:有合法元素、空单元、有已删除元素 */
typedef enum { Legitimate, Empty, Deleted } EntryType;
typedef struct HashEntry Cell; /* 散列表单元类型 */
struct HashEntry{
ElementType Data; /* 存放元素 */
EntryType Info; /* 单元状态 */
};
typedef struct TblNode *HashTable; /* 散列表类型 */
struct TblNode { /* 散列表结点定义 */
int TableSize; /* 表的最大长度 */
Cell *Cells; /* 存放散列单元数据的数组 */
};
HashTable BuildTable(int *find,int num,int tablelen); /* 裁判实现,细节不表 */
Position Hash( ElementType Key, int TableSize )
{
return (Key % TableSize);
}
long getTime()
{
struct timeb tb;
ftime(&tb);
//前面是毫秒,后面是微秒
return tb.time*1000+tb.millitm;
}
#define ERROR -1
Position Find( HashTable H, ElementType Key );
int main()
{
HashTable H;
int num = 1000000;
int len = 1000000;
int find;
Position P;
H = BuildTable(&find,num,len);
long t1 = getTime();
P = Find(H, find);
long t2 = getTime();
if (P==ERROR)
printf("ERROR: %d is not found and the table is full,use %ldms\n", find,t2-t1);
else if (H->Cells[P].Info == Legitimate)
printf("散列表(%d)%d is at position %d,use %ldms\n",num, find, P,t2-t1);
else
printf("%d is not found. Position %d is returned,use %ldms\n", find, P,t2-t1);
return 0;
}
/* 你的代码将被嵌在这里 */
Position Find( HashTable H, ElementType Key ){
int maxsize = H->TableSize;
int d = 0;//增量序列
Position p = Hash(Key,H->TableSize);
while(1){
if(H->Cells[p].Info == Empty || H->Cells[p].Data == Key){
return p;
}
if(d < maxsize-1){
d++;
}else{
break;
}
p = (Hash(Key,H->TableSize)+d)%maxsize;
}
return ERROR;
}
HashTable BuildTable(int *find,int num,int tablelen){
HashTable t = (HashTable)malloc(sizeof(TblNode));//初始化
t->Cells = (Cell*)malloc(sizeof(Cell)*tablelen);
t->TableSize = tablelen;
srand(time(NULL));
int temp;
int flag = 1;//判断又没有找到位置
for(int i = 0;i < num;i++)
t->Cells[i].Info = Empty;//初始化状态
for(int i = 0;i < num;i++){
temp = rand()%(num+1);
int p = Hash(temp,num);
if(i == (num-1)/2)
*find = temp;
while(t->Cells[p].Info == Legitimate){//处理冲突
int d = 0;
if(d < num-1){
d++;
}else{
flag = 0;
break;
}
p = (Hash(p,t->TableSize)+d)%t->TableSize;
}
if(flag){
t->Cells[p].Data = temp;
t->Cells[p].Info = Legitimate;
}
}
return t;
}