十.用C语言实现查找算法 (1)顺序查找;(2)二分查找(折半查找);(3)二叉排序树;(4)哈希查找
2013-08-16 07:59
746 查看
程序名称:Search.cpp // 程序功能:采用结构化方法设计程序,实现多种查找算法。 // 程序作者:*** // 最后修改日期:2011-3-3 #include"iostream" #include"stdlib.h" #include"stdio.h" #include "malloc.h" #define MAX 11 using namespace std; typedef int ElemType ; //顺序存储结构 typedef struct { ElemType *elem; //数据元素存储空间基址,建表时按实际长度分配,号单元留空 int length; //表的长度 } SSTable; void Create(SSTable *table, int length); void Destroy(SSTable *table); int Search_Seq(SSTable *table, ElemType key); void Traverse(SSTable *table, void (*visit)(ElemType elem)); // 构建顺序表 void Create(SSTable **table, int length) { SSTable *t = (SSTable*) malloc(sizeof(SSTable));//分配空间 t->elem=(ElemType*)malloc(sizeof(ElemType)*(length+1)); t->length=length; *table=t; } // 无序表的输入 void FillTable(SSTable *table) { ElemType *t=table->elem; //for循环,输入各个元素 for(int i=0; i<table->length; i++) { t++; scanf("%d", t);//输入元素 getchar(); } } // 销毁表 void Destroy(SSTable *table) { free(table->elem);//释放元素空间 free(table);//释放表的空间 } // 打印查找表 void PrintTable(SSTable *table) { int i;//定义变量 ElemType *t=table->elem; for(i=0; i<table->length; i++)//进入循环,依次打印表中元素 { t++; printf("%d ", *t);//打印输出 } printf("\n"); } //哨兵查找算法 int Search_Seq(SSTable *table, ElemType key) { table->elem[0]=key;//设置哨兵 int result=0; // 找不到时,返回 int i; for (i=table->length; i>=1;i--) { if (table->elem[i]==key) { result=i; break; } } return result;//返回结果 } void printSeq() { //先设置几个变量 SSTable *table; int r; int n; ElemType key; printf("请输入元素个数:"); scanf("%d",&n);//输入元素个数 Create(&table, n);//建立表 printf("请输入");cout<<n;printf("个值:"); FillTable(table);//输入无序表的值 printf("您输入的%d 个值是:\n",n); PrintTable(table);//打印无序表 printf("请输入关键字的值:"); scanf("%d",&key); printf("\n"); printf("顺序查找法运行结果如下:\n\n "); Search_Seq(table,key);//哨兵查找算法 r=Search_Seq(table,key); if( r>0) { printf(" 关键字%d 在表中的位置是:%d\n",key, r);//打印关键字在表中的位置 printf("\n"); } else //查找失败 { printf ("查找失败,表中无此数据。\n\n"); } } // 排序算法 void Sort(SSTable *table ) { int i, j; ElemType temp; for (i=table->length; i>=1 ;i--) // 从前往后找 { for (j=1; j<i; j++) { if(table->elem[j]>table->elem[j+1]) { temp=table->elem[j]; table->elem[j]=table->elem[j+1]; table->elem[j+1]=temp; } } } } // 二分法查找(非递归) int Search_Bin(SSTable *table, ElemType key) { int low=1; int high=table->length; int result=0; // 找不到时,返回 while(low <= high)//low不大于high时 { int mid=(low+high)/2; if(table->elem[mid]==key)//如果找到 { result=mid; break; } else if(key<table->elem[mid])//如果关键字小于mid对应的值 { high=mid-1; } else //否则的话 { low=mid+1; } } return result;//返回结果 } void printBin() { //声明变量 SSTable *table; int r; int n; ElemType key; printf("请输入元素个数:"); scanf("%d",&n); Create(&table, n);//建立表 printf("请输入");cout<<n;printf("个值:"); FillTable(table);//输入无序表的值 printf("您输入的%d 个值是:\n",n); PrintTable(table);//打印无序表 printf("请输入关键字的值:"); scanf("%d",&key); printf("\n"); Sort(table);//对无序表进行排序 printf("数据排序后的顺序如下:\n\n "); PrintTable(table);//打印有序表 printf("\n"); printf("二分查找法的运行结果如下:\n\n "); r=Search_Bin(table,key);//二分(非递归)查找算法 if( r>0) printf("关键字%d 在表中的位置是:%d\n",key, r); else { printf ("查找失败,表中无此数据。\n\n"); } } //二叉排序树 typedef struct BiTnode //定义二叉树节点 { int data; //节点的值 struct BiTnode *lchild,*rchild;//节点的左孩子,节点的右孩子 }BiTnode,*BiTree; //查找(根据节点的值查找)返回节点指针 BiTree search_tree(BiTree T,int keyword,BiTree *father) { BiTree p;// 临时指针变量 *father = NULL;//先设其父亲节点指向空 p = T;//p赋值为根节点(从根节点开始查找) while (p && p->data!=keyword)//如果不是p不指向空且未找到相同值的节点 { *father = p;//先将父亲指向自己(注意:这里传过来的father是二级指针) if (keyword < p->data)//如果要找的值小于自己的值 p = p->lchild;// 就向自己的左孩子开始找 else p = p->rchild;//否则向自己的右孩子开始查找 } return p;//如果找到了则返回节点指针 } BiTree creat_tree(int count) { BiTree T,p;//设置两个临时变量T,p int i = 1; while (i <= count) { if (i == 1)//如果i=1,说明还是空树 { p = (BiTnode *)malloc(sizeof(BiTree));//使p指向新分配的节点 if (!p)//分配未成功 return NULL; T = p;//分配成功,T=p( 这里实际上T就是根节点) scanf("%d",&p->data);//输入p指向节点的值 p->lchild = p->rchild = NULL;//p的左孩子和右孩子都指向空 i++; } else { int temp;// 如果不是空树 scanf("%d",&temp);//输入节点的值 search_tree(T,temp,&p);//查找节点要插入的位置。(T是根节点,插入的节点的值,父亲节点的地址) if (temp < p->data)//如果插入的值小于父亲节点的值 { p->lchild = (BiTnode *)malloc(sizeof(BiTnode));//那么就为父亲节点的左孩子分配一个节点空间,并指向这个空间 if (!p->lchild) return NULL; p = p->lchild;//分配成功,p指向自己的左孩子 } else// 如果插入的值大于父亲节点的值 { p->rchild = (BiTnode *)malloc(sizeof(BiTnode)); if (!p->rchild) return NULL;//分配不成功,退出 p = p->rchild;//p指向自己的右孩子 } p -> data = temp;//新分配的节点的值赋值为插入的值 p -> lchild = p->rchild = NULL;//使其左右节点均为NULL i++; } } return T;//返回根节点 } void InOrder(BiTree T) { if(T) { InOrder(T->lchild); printf("%d ",T->data); InOrder(T->rchild); } } int insert_tree(BiTree *T,int elem)//插入(根节点,插入的值)返回-1和,-1代表插入失败,代表成功 { BiTree s,p,father; s = (BiTnode *)malloc(sizeof(BiTnode));//s指向新开辟一个节点 if (!s)//为开辟成功 return -1;// 返回值-1 s->data = elem;//新节点的值赋值为插入的值 s->lchild = s->rchild = NULL;//其左右孩子为空 p = search_tree(*T,elem,&father);//p赋值为要插入的节点 if (!p) return -1;//未开辟成功,返回-1 if (father == NULL)//如果父亲节点指向空,说明是空树 *T = s;//让根节点指向s else if (elem < father->data)//否则如果插入的值小于父亲的值 father->lchild = s;//父亲的左孩子赋值为s else father->rchild = s;//否则父亲的右孩子赋值为s return 0;//返回 } //删除树结点的操作 int delete_tree(BiTree *T,int elem) { BiTree s,p,q,father;//声明变量 p = search_tree(*T,elem,&father);//查找 if(!p) return -1; if(!p->lchild)//如果p的左孩子为空 { if (father == NULL) { *T = p->rchild;//T指向左孩子 free(p);//释放p return 0; } if (p == father->lchild)//如果p和father的左孩子相等 father->lchild = p->rchild; //将p的左孩子的值赋给father的左孩子 else father->rchild = p->rchild;//将p的左孩子的值赋给father的右孩子 free(p);//释放p return 0; } else if(!p->rchild) { if (father == NULL)//如果father为空 { *T = p->lchild;//将p的左孩子赋给T free(p);//释放p return 0; } if (p == father->lchild)//如果p等于father的左孩子的值 father->lchild = p->lchild; //将p的左孩子的值赋给father的左孩子 else father->rchild = p->lchild; //将p的左孩子的值赋给father的右孩子 free(p); return 0; } else { q = p; s = p->lchild;//将p的左孩子赋给s while (s->rchild) { q = s; s = s->rchild; } p->data = s->data;//将s的值赋给p if (q != p)//如果q不等于p q->rchild = s->lchild; //将s的左孩子值赋给p的右孩子 else q->lchild = s->lchild; //将s的左孩子值赋给p的右孩子 free(s);//释放s return 0; } } //定义print1()以便调用 void print1() { printf("\t**********************\n"); printf("\t1,输出中序遍历\n"); printf("\t2,插入一个结点\n"); printf("\t3,删除一个结点\n"); printf("\t4,查找一个结点\n"); printf("\t5,返回主菜单\n"); printf("\t**********************\n"); } void printTree() { //声明变量 BiTree T,p; T=NULL; int i,n; ElemType key; printf("请输入结点个数:\n"); scanf("%d",&n);//输入值 printf("请输入");cout<<n;printf("个值:"); T=creat_tree(n);//建立树 print1(); scanf("%d",&i);//输入各个值 while(i!=5)//i不等于5时 { switch(i) { case 1: printf("中序遍历二叉树结果如下:\n"); InOrder(T);//中序遍历 break; case 2: printf("请输入要插入的结点值:"); scanf("%d",&key);//输入要查找的关键字 if(insert_tree(&T,key))//如果插入成功 printf("插入成功!"); else printf("已存在此元素!"); break; case 3: printf("请输入要删除的结点值:"); scanf("%d",&key); //输入要删除的关键字 if(!(delete_tree(&T,key)))//如果删除成功 printf("删除成功!"); else printf("不存在此元素!"); break; case 4: printf("请输入要查找的结点值:"); scanf("%d",&key); //输入要查找的关键字 if(search_tree(T,key,&p))//如果查找成功 printf("查找成功!"); else printf("不存在此元素!"); break; default: printf("按键错误!"); } printf("\n"); print1(); scanf("%d",&i); } } //哈希表 typedef struct { int num; } Elemtype;//定义查找的结点元素 typedef struct { Elemtype *elem; //数据元素存储基址 int count; //数据元素个数 int sizeindex; }HashTable;//定义哈希表 int Hash(int num) { int p; p=num%11; return p; }//定义哈希函数 //冲突处理函数,采用二次探测再散列法解决冲突 int collision(int p,int &c) { int i,q; i=c/2+1; while(i<MAX){ if(c%2==0){ c++; q=(p+i*i)%MAX; if(q>=0) return q; else i=c/2+1; } else{ q=(p-i*i)%MAX; c++; if(q>=0) return q; else i=c/2+1; } } return 0; } void InitHash(HashTable *H)//创建哈希表 { int i; H->elem=(Elemtype *)malloc(MAX*sizeof(Elemtype)); H->count=0; H->sizeindex=MAX; for(i=0;i<MAX;i++) H->elem[i].num=0;//初始化,使SearHash函数能判断到底有没有元素在里面 } int SearHash(HashTable H,int key,int *p)//查找函数 { *p=Hash(key); while(H.elem[*p].num!=key&&H.elem[*p].num!=0) *p=*p+1; if(H.elem[*p].num==key) return 1; else return 0; } void InsertHash(HashTable *H,Elemtype e) {//如果查找不到就插入元素 int p; SearHash(*H,e.num,&p); //查找 H->elem[p]=e; ++H->count; } void printHash()//调用哈希表 { HashTable H; int p,key,i,n; Elemtype e; InitHash(&H); printf("输入数据个数(<11 ):"); scanf("%d",&n); printf("请输入各个值:"); for(i=0;i<n;i++) {//输入n个元素 scanf("%d",&e.num);//输入数字 if(!SearHash(H,e.num ,&p)) { InsertHash(&H,e );//插入元素 } else printf("已经存在\n");//否则就表示元素的数字已经存在 } printf("输入查找的数字:"); scanf("%d",&key);//输入要查找的数字 if(SearHash(H,key,&p))//能查找成功 { printf("查找成功!");//输出位置 } else printf(" 不存在此元素!"); } void print() { printf("\t**********************\n"); printf("\t1,顺序查找\n"); printf("\t2,二分查找\n"); printf("\t3,二叉排序树\n"); printf("\t4,哈希查找\n"); printf("\t5,退出程序\n"); printf("\t**********************\n"); } // 主函数 int main(int argc, char* argv[]) { int i;//定义变量 print(); scanf("%d",&i);//输入要数字选择要使用的查找方法 while(i!=5)//i不等于5时 { switch(i) { case 1://i=1时 printf("顺序查找法:\n"); printSeq();//顺序查找法 break;//跳出循环} case 2: printf("二分查找法:\n"); printBin();//二分查找法 break; //跳出循环 case 3: printf("二叉排序树:\n"); printTree();//二叉排序树 break; //跳出循环 case 4: printf("哈希查找法:\n"); printHash();//哈希查找法 break; //跳出循环 default: printf("按键错误!"); } printf("\n"); print();//调用函数print() scanf("%d",&i); } return 0;//返回0 } (1)首主菜单:首先出现主菜单,通过选择相应数字进行相应功能的实现,如图所示: 图4.2.1 主菜单 (2)通过主菜单按键选择1进入顺序查找功能,输入元素个数,然后输入这几个元素的值,用户再输入需要查询的数字即可得出查找结果,如果查找成功则显示出关键字所在的位置,否则显示“查找失败,表中无此数据”,图4.2.2示: 图4.2.2 顺序查找 (3)通过主菜单按键选择2进入二分查找功能,根据提示输入元素个数,再输入这几个值,然后输入要查找的关键字,系统排序后会显示该关键字在顺序表中的位置,否则显示“查找失败,表中无此数据”,如图4.2.3所示: 图4.2.3 查询功能 (4)a.通过主菜单按键选择3进入二叉排序树功能,首先输入结点个数及结点的值建立二叉排序树,然后便进入一个菜单提示选择二叉排序树的某个功能如图4.2.4a所示: 图4.2.4a 二叉排序树功能菜单 b.中序遍历二叉排序树,如图4.2.4b所示: 图4.2.4b 中序遍历二叉排序树 c.插入一个结点,如图4.2.4c所示: 图4.2.4c二叉排序树插入一个结点 d.删除一个结点,如图4.2.4d所示: 图4.2.4d 二叉排序树删除一个结点 e.查找一个结点,如图4.2.4e所示: 图4.2.4e 二叉排序树查找一个结点 (5)通过主菜单按键选择4进入哈希查找功能,根据提示输入元素个数,再输入这几个值,然后输入要查找的关键字,找到则显示“查找成功!”,否则显示“不存在此元素”,如图4.2.5所示: 图4.2.5 哈希查找法
相关文章推荐
- Java实现三种常用的查找算法(顺序查查找,折半查找,二叉排序树查找)
- 使用PHP描述顺序查找和二分查找(也叫做折半查找)算法,顺序查找必须考虑效率,对象可以是一个有序数组
- 数据结构编程笔记二十五:第九章 查找 二叉排序树(动态查找表)查找算法的实现
- 【查找算法】——顺序查找、折半查找、分块查找(索引查找)
- C语言查找算法之顺序查找、二分查找(折半查找)
- 数据结构 c语言 顺序查找算法(linux下实现)
- C语言实现折半查找(二分查找)的算法
- 数据结构 查找及排序算法、直接插入排序及顺序查找(c语言实现)
- PHP 顺序查找和二分查找(也叫做折半查找)算法
- 采用二分查找(即折半查找)的方法实现查找
- 顺序查找 折半查找 二叉排序树
- C语言实现哈希链表查找
- Java中常用的查找算法 - 顺序查找和二分查找
- java实现查找算法——折半查找(二分查找)
- objecttive-C语言使用二叉排序树实现查找、插入、删除、查看元素
- C语言设置监视哨的顺序查找、折半查找算法的实现
- C语言实现顺序表和有序表的查找以及有序表的递归查找
- C语言实现顺序表的初始化,插入,删除,查找
- C/C++查找之一(顺序查找、折半查找(二分查找))
- c++实现顺序查找,折半查找