C语言-中级阶段-15考研必会的查找算法&考研真题实战

本文详细介绍了顺序查找、折半查找以及二叉排序树的原理和C语言实战示例,包括数组排序、中序遍历和递归删除操作,展示了如何在有序列表中高效查找元素。
摘要由CSDN通过智能技术生成

一、顺序查找原理及实战

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值