一、顺序查找原理及实战
1.顺序查找原理
2.代码实战
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int ElemType;
typedef struct {
ElemType* elem;//整型指针,申请的堆空间的起始地址存入elem
int TableLen;//存储动态数组里边元素的个数
}SSTable;
void ST_Init(SSTable &ST,int len)
{
//多申请了一个位置,为了存哨兵,不使用哨兵也可以,为了和王道书保持一致
ST.TableLen=len+1;
ST.elem= (ElemType*)malloc(sizeof(ElemType)*ST.TableLen);
int i;
srand(time(NULL));//随机数生成,考研不需要掌握
for (i = 1; i < ST.TableLen; i++)//因为第0个是哨兵,所以从1随机
{
ST.elem[i] = rand() % 100;//为了随机生成的数都在0到99之间
}
}
//打印顺序表
void ST_print(SSTable ST)
{
int i;
for(i=1;i<ST.TableLen;i++)
{
printf("%3d",ST.elem[i]);
}
printf("\n");
}
int Search_Seq(SSTable ST,ElemType key)
{
ST.elem[0]=key;//key存在零号位置,作为哨兵,有了这个,我们在循环时,可以少写一个i>=0判断
int i;
for(i=ST.TableLen-1;ST.elem[i]!=key;i--);//从后往前找,找到了,i就是刚好是对应的位置
return i;
}
//顺序查找
int main() {
SSTable ST;
ST_Init(ST, 10);
ST_print(ST);//打印顺序表中元素
ElemType key;
printf("please input search key:\n");
scanf("%d",&key);
int pos;
pos = Search_Seq(ST, key);
if(pos)
{
printf("find key,pos=%d\n",pos);
}else{
printf("not find\n");
}
return 0;
}
一些注意:
二、 折半查找原理及实战
1.原理解析
注意:要抓住前提是必须有序的顺序表,如果不是有序的不适用;针对顺序表有序,我们使用qsort进行排序(qsort用来排序用,只能用于数组的排序)
qsort规定如果left指针指向的值大于right指针指向的值,返回正值,小于,返回负值,相等返回0
2.代码实战
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int ElemType;
typedef struct{
ElemType *elem;
int Tablelen;
}SSTable;
void Init_Table(SSTable &ST,ElemType len)
{
ST.Tablelen=len;
ST.elem=(ElemType*)malloc(sizeof(ElemType)*ST.Tablelen);
int i;
srand(time(NULL));
for(i=0;i<ST.Tablelen;i++)
{
ST.elem[i]=rand() % 100;
}
}
void Print_Table(SSTable ST)
{
int i;
for(i=0;i<ST.Tablelen;i++)
{
printf("%3d",ST.elem[i]);
}
printf("\n");
}
int BinarySearch(SSTable ST,ElemType key)
{
int low = 0, high = ST.Tablelen-1, mid;
while(low<=high)
{
mid = (low + high) / 2;
if (key > ST.elem[mid]) {
low = mid + 1;
} else if (key < ST.elem[mid]) {
high = mid - 1;
} else {
return mid;
}
}
return -1;
}
//函数名中存储的是函数的入口地址,也是一个指针,是函数指针类型
//left指针和right指针是指向数组中的任意两个元素
//qsort规定如果left指针指向的值大于right指针指向的值,返回正值,小于,返回负值,相等返回0
int compare(const void *left,const void *right)
{
return *(ElemType*)left-*(ElemType*)right;
}
int main() {
SSTable ST;
Init_Table(ST,10);
Print_Table(ST);
qsort(ST.elem,ST.Tablelen,sizeof(ElemType),compare);
Print_Table(ST);
printf("please input search key:\n");
ElemType pos,key;
scanf("%d",&key);
pos=BinarySearch(ST,key);
if(pos!=-1)
{
printf("this element located %d\n",pos);
} else{
printf("not find\n");
}
return 0;
}
三、二叉排序树原理解析及实战
1.原理解析
注意:为什么二叉排序树只会考中序遍历输出?
因为中序遍历刚好对应的是从小到大顺序输出元素,刚好可以验证二叉排序树建树是否成功
注意:二叉排序树的最大查找次数是树的高度
2.代码实战
#include <stdio.h>
#include <stdlib.h>
typedef int KeyType;
typedef struct BLTnode{
KeyType key;
struct BLTnode *lchild,*rchild;
}BLTnode,*BiTree;
int BLTInsert(BiTree &T,KeyType x)
{
if(NULL==T)
{
T=(BiTree)calloc(1,sizeof(BLTnode));
T->key=x;
return 1;
}
BiTree Tnew=(BiTree)calloc(1,sizeof(BLTnode));
Tnew->key=x;
BiTree p=T,parent;
while(p)
{
parent=p;
if(x>p->key)
{
p=p->rchild;
}else if(x<p->key)
{
p=p->lchild;
}else{
return 0;
}
}
if(x>parent->key)
{
parent->rchild=Tnew;
}else if(x<parent->key)
{
parent->lchild=Tnew;
}
}
void BLTCreate(BiTree &T,KeyType str[],KeyType count)
{
int i;
for(i=0;i<count;i++)
{
BLTInsert(T,str[i]);
}
}
void InOrder(BiTree T)
{
if(T!=NULL)
{
InOrder(T->lchild);
printf("%3d",T->key);
InOrder(T->rchild);
}
}
BiTree BLTSearch(BiTree T,KeyType value,BiTree &parent)
{
parent=NULL;
while(T!=NULL && value!=T->key)
{
parent=T;
if(value>T->key)
{
T=T->rchild;
}else if(value<T->key)
{
T=T->lchild;
}
}
return T;
}
int main() {
BiTree T=NULL;
KeyType str[7]={54,20,66,40,28,79,58};
BLTCreate(T,str,7);
InOrder(T);
printf("\n");
BiTree parent,search;
search=BLTSearch(T,28,parent);
if(search)
{
printf("search success,this element is %d\n",search->key);
}else{
printf("not find\n");
}
return 0;
}
3.二叉排序树删除实战(递归)
#include <stdio.h>
#include <stdlib.h>
typedef int KeyType;
typedef struct BLTnode{
KeyType key;
struct BLTnode *lchild,*rchild;
}BLTnode,*BiTree;
int BLTInsert(BiTree &T,KeyType x)
{
if(NULL==T)
{
T=(BiTree)calloc(1,sizeof(BLTnode));
T->key=x;
return 1;
}
BiTree Tnew=(BiTree)calloc(1,sizeof(BLTnode));
Tnew->key=x;
BiTree p=T,parent;
while(p)
{
parent=p;
if(x>p->key)
{
p=p->rchild;
}else if(x<p->key)
{
p=p->lchild;
}else{
return 0;
}
}
if(x>parent->key)
{
parent->rchild=Tnew;
}else if(x<parent->key)
{
parent->lchild=Tnew;
}
}
void BLTCreate(BiTree &T,KeyType str[],KeyType count)
{
int i;
for(i=0;i<count;i++)
{
BLTInsert(T,str[i]);
}
}
void InOrder(BiTree T)
{
if(T!=NULL)
{
InOrder(T->lchild);
printf("%3d",T->key);
InOrder(T->rchild);
}
}
void BLTDelete(BiTree &T,KeyType key) //删除是可能改变根结点的
{
if(NULL==T)
{
return;
}
if(T->key>key)
{
BLTDelete(T->lchild,key);
} else if(T->key<key)
{
BLTDelete(T->rchild,key);
} else{
if(NULL==T->lchild)
{
BiTree TemNode=T;
T=T->rchild;
free(TemNode);
}else if(NULL==T->rchild)
{
BiTree TemNode=T;
T=T->lchild;
free(TemNode);
}else{
BiTree TemT=T->lchild;
while(TemT!=NULL)
{
TemT=TemT->rchild;
}
T->key=TemT->key;
BLTDelete(T->lchild,TemT->key);
}
}
}
int main() {
BiTree T=NULL;
KeyType str[7]={54,20,66,40,28,79,58};
BLTCreate(T,str,7);
InOrder(T);
printf("\n");
BLTDelete(T,79);
InOrder(T);
printf("\n");
}
注:左右子树都不为空的处理过程
四、2014年42题讲解
* 代码实战:
#include <stdio.h>
typedef int ElemType;
int MiddleSearch(ElemType a[],ElemType b[],ElemType count)
{
ElemType s1=0,l1=count-1,s2=0,l2=count-1,m1,m2;
while(s1!=l1 || s2!=l2)
{
m1=(s1+l1)/2,m2=(s2+l2)/2; //m的运算应当在循环之内
if(a[m1]==b[m2])
{
return a[m1]; //这里应当返回的是具体值,不是一个角标
}else if(a[m1]>b[m2])
{
if((s1+l1)%2==0)
{
l1=m1;
s2=m2;
}else{
l1=m1;
s2=m2+1;
}
}else{
if((s1+l1)%2==0)
{
l2=m2;
s1=m1;
}else{
l2=m2;
s1=m1+1;
}
}
}
return (a[s1]<b[s2])?a[s1]:b[s2]; //这里应当返回的是具体值,不是一个角标
}
int main() {
ElemType a[5]={11,13,15,17,19};
ElemType b[5]={2,4,6,8,20};
ElemType search;
search=MiddleSearch(a,b,5);
printf("mid=%d\n",search);
return 0;
}