现在的位置: 首页 > 综合 > 正文

数据结构学习笔记 — 查找(静态查找表)

2013年10月02日 ⁄ 综合 ⁄ 共 5257字 ⁄ 字号 评论关闭

1. 引言 

本文主要讲解静态查找表。静态查找表在查找的过程中不改变表的状态——不插不删。他适合用于不变动或不常变动的表的查

找。如高考成绩表、本单位职工信息表等。下面分别介绍顺序查找,有序表的折半查找,静态树表的查找。


2. 静态查找表

(1)顺序查找、有序表的折半查找

#include "ds.h"

#define TEST_BIN

#define		EQ(a, b)		((a) == (b))
#define		LT(a, b)		((a) < (b))
#define		LQ(a, b)		((a) <= (b))

#define		key				number
#define 	N 				5
typedef 	long			KeyType;

struct ElemType
{
	long 	number;
	char 	name[13];
	int 	politics;
	int 	Chinese;
	int		English;
	int 	math;
	int		physics;
	int		chemistry;
	int		biology;
	int		total;
};

struct SSTable
{
	ElemType	*elem;
	int			length;
};

void Creat_Seq(SSTable &ST, ElemType r[], int n)
{
	int 	i;
	ST.elem = (ElemType*)malloc(sizeof(ElemType)*(n+1));
	if (!ST.elem)	exit(OVERFLOW);
	
	for (i = 1; i <= n; ++i)
	{
		ST.elem[i] = r[i-1];
	}
	ST.length = n;
}

void Ascend(SSTable &ST)
{
	int 	i, j, k;
	
	for (i = 1; i <= ST.length; ++i)
	{
		k = i;
		ST.elem[0] = ST.elem[i];
		
		for (j = i + 1; j <= ST.length; j++)
			if LT(ST.elem[j].key, ST.elem[0].key)
			{
				k = j;
				ST.elem[0] = ST.elem[j];
			}
		
		if (k != i)
		{
			ST.elem[k] = ST.elem[i];
			ST.elem[i] = ST.elem[0];
		}
	}
}

void Creat_Ord(SSTable &ST, ElemType r[], int n)
{
	Creat_Seq(ST, r, n);
	Ascend(ST);
}

void Destroy(SSTable &ST)
{
	if (ST.elem)
		free(ST.elem);
	ST.elem = NULL;
	ST.length = 0;
}

int Search_Seq(SSTable ST, KeyType key)
{
	int 	i;
	for (i = ST.length; !EQ(key, ST.elem[i].key); --i);
	return i;
}

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

void Traverse(SSTable ST, void (*visit)(ElemType))
{
	int 		i;
	ElemType	*p;
	p = ++ST.elem;
	for (i = 1; i <= ST.length; ++i)
		visit(*p++);
}


void print(ElemType c) // Traverse()调用的函数
{
   printf("%-8ld%-12s%4d%5d%5d%5d%5d%5d%5d%5d\n",c.number,c.name,c.politics,
	   c.Chinese,c.English,c.math,c.physics,c.chemistry,c.biology,c.total);
}

int main()
{
   	ElemType r[N] = {
{179328,"hefangfang",85,89,98,100,93,80,47},
{179325,"chenhong",85,86,88,100,92,90,45},
{179326,"luhua",78,75,90,80,95,88,37},
{179327,"zhangping",82,80,78,98,84,96,40},
{179324,"zhaoxiaoyi",76,85,94,57,77,69,44}}; // 数组不按关键字有序
   	SSTable st;
   	int i;
   	long s;
   	for(i=0;i<N;i++) // 计算总分
    	r[i].total=r[i].politics+r[i].Chinese+r[i].English+r[i].math+r[i].physics+
	 	r[i].chemistry+r[i].biology;
#ifdef TEST_BIN
   	Creat_Ord(st,r,N); // 由数组r产生非降序静态查找表st
#else
   	Creat_Seq(st,r,N); // 由数组r产生顺序静态查找表st
#endif
   	printf("准考证号  姓名  政治 语文 外语 数学 物理 化学 生物 总分\n");
   	Traverse(st,print); // 按顺序输出静态查找表st
   	printf("请输入待查找人的考号: ");
   	scanf("%ld",&s);
#ifdef TEST_BIN
   	i=Search_Bin(st,s); // 折半查找
#else
	i=Search_Seq(st,s); // 顺序查找
#endif
   	if(i)
     	print(st.elem[i]);
   	else
     	printf("没找到\n");
   	Destroy(st);
}

(2)静态树表的查找

静态树表是把有序的静态查找表根据数据被查找的概率生成一棵二叉树,使得从二叉树的根结点起,查找左右子树的概率大致相等,使平均查找长度较短。若每个数据的查找的概率相等,直接使用折半法即可,不必生成二叉树。

#include "ds.h"

#define		EQ(a, b)		((a) == (b))
#define		LT(a, b)		((a) < (b))
#define		LQ(a, b)		((a) <= (b))

#define 	N 	 	9
typedef		char	KeyType;
struct 	ElemType
{
	KeyType		key;
	int			weight;
};
struct SSTable
{
   	ElemType 	*elem; 	// 数据元素存储空间基址,建表时按实际长度分配,0号单元留空
   	int 		length; // 表长度
};
typedef		ElemType	TElemType;
typedef struct BiTNode
{
   	TElemType 	data;
   	BiTNode 	*lchild, *rchild; // 左右孩子指针
}BiTNode,*BiTree;


void Creat_Seq(SSTable &ST, ElemType r[], int n)
{
	int 	i;
	ST.elem = (ElemType*)malloc(sizeof(ElemType)*(n+1));
	if (!ST.elem)	exit(OVERFLOW);
	
	for (i = 1; i <= n; ++i)
	{
		ST.elem[i] = r[i-1];
	}
	ST.length = n;
}

void Ascend(SSTable &ST)
{
	int 	i, j, k;
	
	for (i = 1; i <= ST.length; ++i)
	{
		k = i;
		ST.elem[0] = ST.elem[i];
		
		for (j = i + 1; j <= ST.length; j++)
			if LT(ST.elem[j].key, ST.elem[0].key)
			{
				k = j;
				ST.elem[0] = ST.elem[j];
			}
		
		if (k != i)
		{
			ST.elem[k] = ST.elem[i];
			ST.elem[i] = ST.elem[0];
		}
	}
}

void Creat_Ord(SSTable &ST, ElemType r[], int n)
{
	Creat_Seq(ST, r, n);
	Ascend(ST);
}

void Destroy(SSTable &ST)
{
	if (ST.elem)
		free(ST.elem);
	ST.elem = NULL;
	ST.length = 0;
}

int Search_Seq(SSTable ST, KeyType key)
{
	int 	i;
	for (i = ST.length; !EQ(key, ST.elem[i].key); --i);
	return i;
}

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

void Traverse(SSTable ST, void (*visit)(ElemType))
{
	int 		i;
	ElemType	*p;
	p = ++ST.elem;
	for (i = 1; i <= ST.length; ++i)
		visit(*p++);
}



// 由有序表R[low..high]及其累计权值表sw(其中sw[0]==0)递归构造次优查找树T。算法9.3
Status SecondOptimal(BiTree &T, ElemType R[], int sw[], int low, int high)
{
	int 	i, j;
	double	min, dw;
	i = low;
	min = fabs(sw[high] - sw[low]);
	dw = sw[high] + sw[low - 1];
	for (j = low + 1; j < high; ++j)	 // 选择最小的△Pi值
     	if (fabs(dw-sw[j]-sw[j-1]) < min)
     	{
       		i = j;
       		min = fabs(dw-sw[j]-sw[j-1]);
     	}
   	if(!(T=(BiTree)malloc(sizeof(BiTNode))))
     	return ERROR;
   	T->data=R[i]; // 生成结点
   	if(i==low)
     	T->lchild=NULL; // 左子树空
   	else
     	SecondOptimal(T->lchild,R,sw,low,i-1); // 构造左子树
   	if(i==high)
     	T->rchild=NULL; // 右子树空
   	else
     	SecondOptimal(T->rchild,R,sw,i+1,high); // 构造右子树
   	return OK;
}

void FindSW(int sw[], SSTable ST)
{
	int 	i;
	sw[0] = 0;
	for (i = 1; i <= ST.length; i++)
		sw[i] = sw[i - 1] + ST.elem[i].weight;
}

typedef 	BiTree		SOSTree;	// 次优查找树采用二叉链表的存储结构
void CreateSOSTree(SOSTree &T,SSTable ST)
{ // 由有序表ST构造一棵次优查找树T。ST的数据元素含有权域weight。算法9.4
   	int sw[N+1]; // 累计权值
   	if(ST.length==0)
     	T=NULL;
   	else
   	{
     	FindSW(sw,ST); // 按照有序表ST中各数据元素的weight域求累计权值表sw
     	SecondOptimal(T,ST.elem,sw,1,ST.length);
   	}
}

// 在次优查找树T中查找关键字等于key的元素。找到则返回OK,否则返回FALSE
Status Search_SOSTree(SOSTree &T,KeyType key)
{ 
   	while(T) // T非空
     	if(T->data.key==key)
       		return OK;
     	else if(T->data.key>key)
       		T=T->lchild;
     	else
       		T=T->rchild;
   	return FALSE; // 顺序表中不存在待查元素
}

void print(ElemType c) // Traverse()调用的函数
{
   	printf("(%c %d) ",c.key,c.weight);
}

int main()
{
   	SSTable st;
   	SOSTree t;
   	Status i;
   	KeyType s; // 以教科书例9-1的数据为例
   	ElemType r[N]={{'A',1},{'B',1},{'C',2},{'D',5},{'E',3},{'F',4},{'G',4},{'H',3},{'I',5}};
   	Creat_Ord(st,r,N); // 由全局数组产生非降序静态查找表st
   	Traverse(st,print);
   	CreateSOSTree(t,st); // 由有序表构造一棵次优查找树
   	printf("\n请输入待查找的字符: ");
   	scanf("%c",&s);
   	i=Search_SOSTree(t,s);
   	if(i)
     	printf("%c的权值是%d\n",s,t->data.weight);
   	else
     	printf("表中不存在此字符\n");
}

抱歉!评论已关闭.