1. 程式人生 > >資料結構--C語言--查詢演算法的實現--順序表的查詢

資料結構--C語言--查詢演算法的實現--順序表的查詢

 

1.實驗目的

熟練掌握順序表和有序表的查詢方法,掌握其時間複雜度的分析方法

2.實驗內容

(1)驗證並設計順序表的查詢(順序查詢、折半查詢)演算法

(2)驗證二叉排序樹上的查詢(建立、查詢、插入)演算法

(3)驗證Hash表查詢(Hash函式定義、建立,查詢,插入)演算法

//順序表的順序查詢 折半查詢 二叉排序樹 以數值型關鍵字為例 
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
#define INCRESIZE 20
#define EQ(a,b) a==b
#define LT(a,b) a<b
#define LQ(a,b) a<=b
#define ERROR 0
#define FALSE 0
#define TRUE 1 
#define OK 1

typedef int ElemType;
typedef int KeyType;
typedef int Status;

typedef struct{
	ElemType *base;
	int length;//表長度 0號單元不儲存內容 
}SSTable;

typedef struct BTNode{
	ElemType data;
	struct BTNode *lchild;
	struct BTNode *rchild;
}BTNode,*BiTree;

Status Init_Seq(SSTable &ST){
	ST.base = (ElemType *)malloc(MAXSIZE*sizeof(ElemType));
	if(!ST.base) return ERROR;
	ST.length = 0;
	return OK;
}

Status Creat_Seq(SSTable &ST){
	int count = 1;
	printf("\n構造順序表,輸入-111意為停止輸入\n");
	scanf("%d",ST.base+count);
	while(ST.base[count]!=-111){
		count++;
		if(count>MAXSIZE){
			ST.base = (ElemType *)realloc(ST.base,(MAXSIZE+INCRESIZE)*sizeof(ElemType));
			if(!ST.base) return ERROR;
		}
		scanf("%d",ST.base+count);
	}
	ST.length = --count;
	return OK;
}

int Search_Seq(SSTable ST,KeyType key){//0號單元設哨兵 
	ST.base[0] = key;
	int i;
	for(i=ST.length;*(ST.base+i)!=key;i--) ;//空語句 
	return i;
}

Status Sort(SSTable &ST){
	int min,temp;
	for(int i=1;i<=ST.length;i++){
		min = i;
		for(int j=i;j<=ST.length;j++){
			if(ST.base[min]>ST.base[j]) min = j;
		}
		temp = ST.base[min];
		ST.base[min] = ST.base[i];
		ST.base[i] = temp;
	}
	printf("\n\n排序後的序列為:");
	for(int i=1;i<=ST.length;i++) printf("%d  ",ST.base[i]);
}

int Search_Bin(SSTable ST,KeyType key){
	int low=1,high=ST.length,mid;
	Sort(ST);
	while(low<=high){
		mid = (low+high)/2;
		if(EQ(key,ST.base[mid])) return mid;
		else if(LT(key,ST.base[mid])) high = mid-1;
		else low = mid+1;
	}
	return 0;
}

Status SearchBST(BiTree T,KeyType key,BiTree f,BiTree &p){//查詢成功p為資料所在結點指標 否則是插入位置指標 f是工作指標 始終指向當前查詢結點的父母 
	if(!T){
		p = f;//直接插入在根結點 
		return FALSE;//查詢失敗 
	}else if(EQ(key,T->data)){
		p = T;
		return TRUE;//查詢成功 
	}else if(LT(key,T->data)){
		return SearchBST(T->lchild,key,T,p);//在左子樹中繼續查詢 
	}else{
		return SearchBST(T->rchild,key,T,p);//在右子樹中繼續查詢 
	} 
}

Status InsertBST(BiTree &T,ElemType e){
	BiTree p;
	if(!SearchBST(T,e,NULL,p)){//如果是空樹的話p返回NULL 不是空樹的話f在SearchBST()裡會做改變 最後查詢失敗時p=f是不為空的 
		BiTree s = (BiTree)malloc(sizeof(BTNode));
		s->data = e; s->lchild = s->rchild = NULL;
		if(!p) T=s;//空樹 
		else if(p->data>e) p->lchild = s;//已經查詢到了葉子結點處 
		else p->rchild = s;
		return TRUE;
	}
	return FALSE; 
}

Status CreatBST(BiTree &T){
	printf("\n\n建立一棵二叉排序樹,輸入-111意為停止\n");
	ElemType e;
	scanf("%d",&e);
	while(e!=-111){
		InsertBST(T,e);
		scanf("%d",&e);
	}
	return OK;
}

int main(){
	SSTable ST;
	KeyType key;
	BiTree T=NULL,p=NULL;
	int locate;
	
	Init_Seq(ST);
	Creat_Seq(ST);
	printf("\n\n請輸入待查詢的數:");
	scanf("%d",&key);
	
	if(Search_Seq(ST,key)) printf("\n\n順序查詢結果:%d在順序表中的第%d位\n",key,Search_Seq(ST,key));
	else printf("\n順序查詢失敗 該資料不存在!\n");
	
	locate = Search_Bin(ST,key);
	if(locate) printf("\n折半查詢結果:%d在有序表中的第%d位\n",key,locate);
	else printf("\n\n折半查詢失敗 該資料不存在!\n");
	
	
	CreatBST(T);
	printf("\n請輸入待查詢的數:");
	scanf("%d",&key);
	SearchBST(T,key,NULL,p);
	if(SearchBST(T,key,NULL,p)) printf("查詢成功!\n");
	else printf("查詢失敗!\n");
} 

 

//雜湊表的定義 建立 查詢 插入 以數值型元素為例 
#include<stdio.h>
#include<stdlib.h>

#define EQ(a,b) a==b
#define LT(a,b) a<b
#define LQ(a,b) a<=b
#define MAXSIZE 40
#define INCRESIZE 10
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
#define NULLKEY -111

typedef int KeyType;
typedef int Status;
typedef int ElemType;

typedef struct{
	ElemType *base;//資料元素儲存基址 動態分配陣列 
	int count;//當前資料元素的個數 
	int sizeindex;//hashsize[sizeindex]為當前容量 
}HashTable;

//初始化 
Status InitHash(HashTable &H){
	H.base = (ElemType *)malloc(MAXSIZE*sizeof(ElemType));
	if(!H.base) exit(DUPLICATE);
	H.sizeindex = MAXSIZE;
	H.count = 0;
	for(int i=0;i<H.sizeindex;i++) H.base[i] = NULLKEY;  
	return SUCCESS;
}

//構造雜湊函式 
Status Hash(ElemType e,int &p){//根據函式計算儲存位置並賦給p
	p =  e%19;//除留餘數法和平方取中法結合構造雜湊函式
	return SUCCESS;
}

Status collision(HashTable H,int &p){//線性探測再散列表 
	int i;
	for(i=p+1;i<H.sizeindex;i++)
		if(H.base[i]==NULLKEY) p=i;
	if(i==H.sizeindex){
		H.base = (ElemType *)realloc(H.base,(H.sizeindex+INCRESIZE)*sizeof(ElemType));
		if(!H.base) exit(DUPLICATE);
		H.sizeindex += INCRESIZE;
		p = H.sizeindex;
	}
	return SUCCESS;
}

//在雜湊表裡查詢key 如果查詢成功 p儲存在表中的下標 返回成功 否則p指示插入位置 返回不成功,c用來計算衝突個數 
Status SearchHash(HashTable H,KeyType key,int &p,int &c){
	Hash(key,p);//用公式來計算他在數組裡的下標
	
	//當該位置中填有記錄 並且與所查詢的關鍵字不相等的時候
	while(H.base[p]!=NULLKEY&&H.base[p]!=key) {
		collision(H,p);//求得下一探測地址
	} 
		
		
	if(EQ(H.base[p],key)) return SUCCESS;
	return UNSUCCESS;//NULLKEY 	
}

//插入
Status InsertHash(HashTable &H,ElemType e){
	int p,c=0;//c初始值為0在建表的時候可以用作參考 
	if(SearchHash(H,e,p,c)){
		return UNSUCCESS;	
	}
	else{
		H.base[p] = e;
		H.count++;
		return SUCCESS;
	}
}

Status CreatHash(HashTable &H){
	InitHash(H);
	ElemType a;
	printf("請構造雜湊表 輸入-111意為停止:\n");
	scanf("%d",&a);
	while(a!=-111){
		if(!InsertHash(H,a)) printf("已存在該關鍵字!\n");
		scanf("%d ",&a);
	}
	return SUCCESS;
}

void Visitall(HashTable H){
	int num = H.count;
	printf("\nresult:");
	for(int i=0;i<H.sizeindex,num!=0;i++){
		if(H.base[i]!=NULLKEY){
			printf("%d ",H.base[i]);
			num--;
		} 
	}
} 

int main(){
	ElemType num;
	int p,c;
	HashTable H;
	CreatHash(H);
	
	Visitall(H);
	printf("\n請輸入你要查詢的關鍵字:");
	scanf("%d",&num);
	if(SearchHash(H,num,p,c)) printf("\n查詢成功!\n");
	else printf("\n查詢失敗!\n");
	
	return 0;
}