15.考研数据结构chatper7查找实战代码

目录

一、顺序查找

(1)定义结构

(2)初始化

(3)查找

(4)输出顺序表

二、折半查找(二分查找)

2.事前准备

(1)创建顺序表

(2)排序

3.思路

三、二叉排序树(二叉查找树)

1.定义

2.创建

3.查找

6.输出

(2)思路(不考虑等于)

四、二叉排序树删除

五、AVL定义

六、RBT定义

七、真题

1.题目 2014-42

2.思路

3.实现


一、顺序查找

(1)定义结构

//顺序查找:顺序表用指针实现
typedef int ElemType;
typedef struct {
    ElemType *elem; //整形指针,存申请的堆空间的地址
    int TableLen;//存个数
}SSTable;

(2)初始化

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 = 0; i < ST.TableLen; ++i)
    {
        ST.elem[i] = rand()%100;//0~99之间
    }
}

(3)查找

//普通
int Sq_Search(SqTable ST,int e){
    for (int i = 0; i < ST.len; ++i) {
        if(i<=ST.len && e == ST.data[i]){
            return i ;
        }
    }
    return -1;
}
int search_seq(SSTable ST,ElemType key){
    ST.elem[0] = key;
    int i;
    for (i = ST.TableLen-1; ST.elem[i]!=key; i--);
    return i;
}

(4)输出顺序表

void ST_Print(SSTable ST){
    int i ;
    for (int i = 1; i < ST.TableLen; ++i) //不输出哨兵
    {
        printf("%-3d",ST.elem[i]);
    }
    printf("\n");
}

二、折半查找(二分查找)

2.事前准备

(1)创建顺序表

见上面顺序查找

(2)排序

使用<stdlib.h>中的qsort(),第一个参数为待排序的数据,第二个为待排序数据的长度,第三个为单个排序数据的大小,第四个为判断规则,需要自己编写函数

compare 函数:两个空类型的指针left和right,当left指向的data大于right返回的data,return正值,小于则返回负值,相等return 0 ,left-right排序结果为升序;降序right-left

	// right 和left 指向arr中任意两个元素
int compare(const void *left,const void *right){
	return *(int*)left - *(int*)right;//升序
	return *(int*)right - *(int*)left;//降序
}

qsort(ST.elem,ST.TableLen,sizeof(ElemType),compare);//排序

3.思路

int BinarySearch(SSTable L,ElemType key){
	int low =0;
	int high = L.TableLen -1;
	int mid;
	while(low <= high){//使mid取到所有情况
		mid = low +  (high-low)/2;
		if(key > L.elem[mid]){
			low = mid + 1;
		}
		else if(key <L.elem[mid]){
			high = mid - 1;
		}else{
			return mid;
		}
	}
	return -1;
}

三、二叉排序树(二叉查找树)

1.定义

typedef int ElemType;

typedef struct BSTNode{
    ElemType data;
    struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

2.创建

//插入单个ele
int Insert(BSTree &T,ElemType e){
    if(T==NULL){
        T = (BSTNode*)malloc(sizeof(BSTNode));
        T->data = e;
        T->lchild =T->rchild= NULL;
        return 1;
    }
    else if(e == T->data) return  0;//相同不插入
    else if(e < T->data) return Insert(T->lchild,e);
    else return Insert(T->rchild,e);
}

//循环插入
void CreateTree(BSTree &T,ElemType e[],int n){
    T = NULL;
    int i;
    for (i = 0; i < n ; i++) {
        Insert(T,e[i]);
    }
}

3.查找

//非递归查找
BSTNode* BSTFind(BSTree T,ElemType e,BSTNode* &parent){//记录目标结点的parent
    parent = NULL;
    while(T!= NULL && e != T->data){
        parent = T;
        if(e > T->data) T = T->rchild;
        else T = T->lchild;
    }
    return T;
}

//递归
BSTNode* BSTFind2(BSTree T,ElemType e){
    if(T == NULL) return NULL;
    if(T->data == e) return T;
    else if(e < T->data) return BSTFind2(T->lchild,e);
    else return BSTFind2(T->rchild,e);
}

6.输出

void print(BSTree T){
    if(T!=NULL){
        print(T->lchild);
        printf("%-3d",T->data);
        print(T->rchild);
    }
}

(2)思路(不考虑等于)

指针T指向待找结点,当该结点大于当前结点,往右走,小于则往左走

找到了T就是插入的位置,那怎么跟前一个结点链接呢?

引入parent结点,在查找之前令 parent=T,找到之后直接parent左右孩子赋值即可

//创建树的空间
void  Create_BST(BiTree &T,KeyType* str,int len){
    //str是整型arr,传入参数中弱化为整型指针
    int i;
    for ( i = 0; i < len; i++)
    {
        BST_Insert(T,str[i]);
    }
}

//插入结点
int BST_Insert(BiTree &T,KeyType k){
    //54,20,66,40,28,79,58
    //为进入的结点申请空间
    BiTree TreeNew = (BiTree)calloc(1,sizeof(BSTNode));
    TreeNew ->key = k;

    if(NULL == T){//空树,插入的是树根
        T = TreeNew;
        return 0;
    }
    //非空,找位置
    BiTree p=T,parent;//p用来查找树
    //p找到待插入的pos,so引入parent
    while(p){//初试不考虑相等元素
        parent = p;
        if(k > p->key){
            p = p->rchild;
        }else if(k<p->key){
            p = p->lchild;
        }else{	// ==
            return -1;//不考,可以不考虑
        }
    }
    //p为null了跳出循环,有了parent
    //but不知道放parent的左孩子还是右孩子
    if(k > parent->key){//用值比较
        parent ->rchild = TreeNew;
    }else if(k < parent->key){
        parent ->lchild = TreeNew;
    }
    return 0;
}

四、二叉排序树删除


//使用递归实现
void DeleteNode(BiTree &root,KeyType x){
    //引用root,为了改变删除结点,直接顶上即可
    if(NULL == root){//空树
        return;
    }
    if(x > root->key){
        DeleteNode(root->rchild,x);
    }
    else if(x < root->key){
        DeleteNode(root->lchild,x);
    }else{//找到了待删除的结点
        if(root->lchild == NULL){
            BiTree TempNode = root;
            root = root->rchild;
            free(TempNode);
        }else if(root->rchild == NULL){
            BiTree TempNode = root;
            root = root->lchild;
            free(TempNode);
        }else{//都不为null
            //左子树的最右结点or右子树的最左结点放到删除结点的位置上
            BiTree TempNode = root->lchild;
            //找到左子树的最右结点
            while(TempNode->rchild){
                TempNode = TempNode->rchild;
            }
            root ->key = TempNode->key;
            //因为root把根结点覆盖
            //在左子树中找到值为待删除的结点值并删除,而不是直接删除tempnode、
            DeleteNode(root->lchild,TempNode->key);
        }
    }
}

五、AVL定义

//AVL
typedef struct AVLNode{
    ElemType data;
    int balance;
    struct AVLNode *lchild,*rchild;
}AVLNode,*AVLTree;

六、RBT定义

//RBT
typedef struct RBTNode{
    ElemType data;
    struct RBTNode *parent;
    struct RBTNode *lchild,*rchild;
    int color;//0表示R,1表示B
}RBTNode,*RBT;

七、真题

1.题目 2014-42

2.思路

二分查找的分治思想

找两个arr的中位数比较大小,小的中位数前面的肯定不是整体的中位数,大的中位数后面的肯定不会是整体的中位数,因此可以舍弃,当每个arr只剩下一个时候,小的就是整体的中位数

3.实现

attn:s、d指向队列头尾,mid是中间元素,当是奇数个元素,小的舍弃中位数之前的,大的到中位数那;偶数个元素时,小的舍弃中位数及其之前的元素,大的舍弃后面的元素,保留中位数

如何确定是否保留呢?若最后就剩俩个,则必须舍弃自己才能剩下1个,so需要舍弃本身

大的如何确定舍弃多少呢?每次两个arr舍弃的个数需要相同,确定d到mid的位置即可

int MidSearch(int *A,int *B,int n){
    int s1 = 0,d1=n-1,m1,s2=0,d2=n-1,m2;
    while(s1!=d1 || s2!=d2){//两个都相等才停止
        m1 = (s1 +d1)/2;
        m2 = (s2 +d2)/2;
        if(A[m1] ==B[m2] ){//相等
            return  A[m1];
        }else if(A[m1] <B[m2]){
            if((s1+d1)%2==0){//奇数个元素
                //例子:一共五个元素,s1=0,d1=4,2的倍数
                s1 = m1;//小的舍弃自己前面元素
                d2 = m2;//大的
            }else {//偶数个元素
                s1 = m1 + 1;//小的舍弃自己及前面元素
                d2 = m2;//大的舍弃后面的保留中间的
            }
        }else{//A[m1] > B[m2]
            if((s1+d1)%2==0){
                d1 = m1;
                s2 = m2;
            }else{
                d1 = m1;
                s2 = m2+1;
            }
        }
    }
    return A[s1] < B[s2] ? A[s1] : B[s2];//返回小的
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

blue_blooded

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值