3/10/24二叉树权值、单链表双指针查找、顺序查找、二分查找、二叉排序树

目录

二叉树带权路径真题2014

单链表查找倒数第k个真题2009

顺序查找

折半查找

二叉排序树

二叉树各叶结点深度即递归层数。

链表查找第k个,快指针先走k个,再一起遍历知道快指针到链表尾。

二分查找注意循环推出条件low<=high。

二叉排序树中序遍历即升序排列顺序。

注意各类型逻辑熟练,其次考虑代码实现。

二叉树带权路径真题2014

//前序遍历,即先序遍历,即深度优先遍历
//deep代表路径长度
int WplPreOrder(BiTree p, int deep) {
    static int wpl = 0;//静态局部变量和全局变量类似,只会初始化一次,区别是只在局部有效
    if (NULL != p) {
        //判断为叶结点是,将对应叶结点weight*deep,加到wpl
        if (p->lchild == NULL && p->rchild == NULL)wpl += p->weight*deep;
//        printf("%c", p->weight);
        WplPreOrder(p->lchild, deep + 1);//递归左子树,路径长度+1
        WplPreOrder(p->rchild, deep + 1);//递归右子树,路径长度+1
    }
    return wpl;
}

int WPL(BiTree tree) {
    return WplPreOrder(tree, 0);
}

单链表查找倒数第k个真题2009

思路:

双指针。fast指针先走k个,随后fast指针和slow指针一同遍历,当fast指针指向NULL时,slow指针指向倒数第k个结点。

顺序查找

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef int ELemType;
typedef struct {
    ELemType *elem;//整型指针,申请的堆空间的起始地址存入elem
    int TableLen;//存储动态数组里面元素的个数
} SSTable;

void STInit(SSTable &ST, int len) {
    //多申请一个位置,存放哨兵,不使用哨兵也可以
    ST.TableLen = len + 1;
    ST.elem = (ELemType *) malloc(sizeof(ELemType) * ST.TableLen);
    srand(time(NULL));//随机数生成
    for (int i = 1; i < ST.TableLen; i++) {//因为第0个是哨兵,所以从1随机
        ST.elem[i] = rand() % 100;//为了随机生成的数据都在1到99之间
    }
}

int SearchSeq(SSTable ST, ELemType key) {
    ST.elem[0] = key;//key存在零号元素作为哨兵,不用在for loop中判断i>=0
    int i = ST.TableLen - 1;
    for (; ST.elem[i] != key; i--);//从后往前找,找到就跳出循环,i刚好是对应的位置
    return i;
}


void STPrint(SSTable ST) {
    for (int i = 1; i < ST.TableLen; i++) {
        printf("%3d", ST.elem[i]);
    }
    printf("\n");
}

int main() {
    SSTable ST;
    STInit(ST, 10);
    STPrint(ST);//打印顺序表中元素
    ELemType key;
    printf("please input search key:\n");
    scanf("%d", &key);
    int pos;
    pos = SearchSeq(ST, key);
    if (pos)printf("find key,pos=%d\n", pos);
    else printf("unfond\n");
    return 0;
}

折半查找

折半查找又称二分查找,仅适用于有序的顺序表。

将查找值key与表中间位置的原元素比较,若相等则查找成功,返回该元素的存储位置;若不等,则所需查找的元素在中间元素以外的前半部分或后半部分继续查找,知道找到为止,或确定找不到。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef int ElemType;
typedef struct {
    ElemType *elem;//整形指针
    int TableLen;//存储动态数组里面的元素个数
} SSTable;

void InitST(SSTable &T, int len) {
    T.TableLen = len;
    T.elem = (ElemType *) malloc(sizeof(ElemType) * T.TableLen);
    srand(time(NULL));//随机数生成
    for (int i = 0; i < T.TableLen; i++) {
        T.elem[i] = rand() % 100;
    }
}

void PrintST(SSTable T) {
    for (int i = 0; i < T.TableLen; i++) {
        printf("%3d", T.elem[i]);
    }
    printf("\n");
}

int BinarySearch(SSTable L, ElemType key) {
    int low = 0;
    int high = L.TableLen - 1;
    int mid;
    while (low <= high) {//low<=high可以让mid既能取到low也能取到high
        mid = (low + high) / 2;
        if (key > L.elem[mid]) low = mid + 1;
        else if (key < L.elem[mid]) high = mid - 1;
        else return mid+1;
    }
    return 0;
}

//函数名中存储的是函数的入口地址,也是一个指针,是函数指针类型
//left和right指向元组中任意两个元素
//qsort规定,若left指向的值大于right指向的值返回正值,小于返回负值,等于返回0
int compare(const void *left, const void *right) {
    return *(ElemType *) left - *(ElemType *) right;
    //return *(ElemType *)right-*(ElemType *)left;//从大到小排序
}

int main() {
    SSTable T;
    InitST(T, 10);//初始化,随机生成10个元素
    PrintST(T);
    qsort(T.elem, T.TableLen, sizeof(ElemType), compare);//排序
    PrintST(T);
    ElemType key;
    printf("please input search key:\n");
    scanf("%d", &key);
    int pos = BinarySearch(T, key);
    if (0==pos)printf("unfind\n");
    else printf("find key %d\n", pos);
    return 0;
}

二叉排序树

二叉排序树(也称二叉查找树),或者是一颗空树,是具有下列特征的二叉树。

  1. 若左子树非空,则左子树上的所有结点的值均小于根结点的值。
  2. 作右子树非空,则右子树上的所有结点的值均大于根节点的值。
  3. 左、右子树也分别是一颗二叉排序树,1、2特征对所有结点适用。

二叉树的最大查找次数是树的高度。

#include <stdio.h>
#include <stdlib.h>

typedef int KeyType;
typedef struct BSTNode {
    KeyType key;
    struct BSTNode *lchild, *rchild;
} BSTNode, *BiTree;

//递归创建二叉查找树
int InsertRecuBST(BiTree &T, KeyType k) {
    if (NULL == T) {
        //为新结点申请空间,第一个结点作为树根,后面递归在进入就不是树根,是为叶子结点
        T = (BiTree) malloc(sizeof(BSTNode));
        T->key = k;
        T->lchild = T->rchild = NULL;
        return 1;//代表插入成功
    } else if (k == T->key) return 0;//发现相同元素不插入
    else if (k < T->key)//若插入结点小于当前结点
        //函数调用结束后,左孩子和原来的父结点关联起来,巧妙利用了引用机制
        return InsertRecuBST(T->lchild, k);
    else
        return InsertRecuBST(T->rchild, k);
}

//非递归创建二叉查找树
int InsertBST(BiTree &T, KeyType k) {
    //新结点申请空间
    BiTree newTree = (BiTree) calloc(1, sizeof(BSTNode));
    newTree->key = k;
    if (NULL == T) {
        T = newTree;
        return 1;
    }
    BiTree p = T, parent;//用来查找树
    //while loop查找叶子节点
    while (p) {
        parent = p;//parent存放父结点
        if (k > p->key) {
            p = p->rchild;
        } else if (k < p->key) {
            p = p->lchild;
        } else {
            return 0;//相等元素不能放入查找树,考研不考虑相等元素存放
        }
    }
    //接下来判断放到父结点左边还是右边
    //成为父结点的右孩子
    if (k > parent->key)parent->rchild = newTree;
        //成为父结点的左孩子
    else parent->lchild = newTree;
    return 1;
}

//树中不放相等元素
void CreateBST(BiTree &T, KeyType *str, int len) {
    for (int i = 0; i < len; i++) {
        InsertBST(T, str[i]);
    }
}

void MidOrder(BiTree T) {
    if (T != NULL) {
        MidOrder(T->lchild);
        printf("%3d", T->key);
        MidOrder(T->rchild);
    }
}

BiTree SearchBST(BiTree T, KeyType k, BiTree &parent) {
    parent = NULL;//防止空树,需要先赋值NULL
    while (T != NULL && k != T->key) {
        parent = T;
        if (k > T->key) T = T->rchild;
        else T = T->lchild;
    }
    return T;
}

int main() {
    BiTree T = NULL;//树根
    KeyType str[7] = {54, 20, 66, 40, 28, 79, 58};
    CreateBST(T, str, 7);
    MidOrder(T);//中序遍历二叉查找树是由小到大的
    printf("\n");
    BiTree search, parent;
    search = SearchBST(T, 40, parent);
    if (search) printf("find key %d", search->key);
    else printf("unfind");
    return 0;
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值