索引顺序表查找和二叉排序树查找

二叉排序树(BST)的定义为:二叉排序树或者是空树,或者是满足下列性质的二叉树:

(1) :若左子树不为空,则左子树上所有结点的值(关键字)都小于根结点的值;

(2) :若右子树不为空,则右子树上所有结点的值(关键字)都大于根结点的值;

(3) :左、右子树都分别是二叉排序树。

 结论:若按中序遍历一棵二叉排序树,所得到的结点序列是一个递增序列。

BST可以用二叉链表来存储:

BST查找思想:

       首先将给定的K值与二叉排序树的根结点的关键字进行比较:若相等: 则查找成功;

① 给定的K值小于BST的根结点的关键字:继续在该结点的左子树上进行查找;

②   给定的K值大于BST的根结点的关键字:继续在该结点的右子树上进行查找。


 索引技术是组织大型数据库的重要技术,索引结构的基本组成是索引表和数据表两部分:

◆ 数据表:存储实际的数据记录;

◆索引表:存储记录的关键字和记录(存储)地址之间的对照表,每个元素称为一个索引项。

 通过索引表可实现对数据表中记录的快速查找。索引表的组织有线性结构和树形结构两种。

顺序索引表是将索引项按顺序结构组织的线性索引表,而表中索引项一般是按关键字排序的,其特点是:

优点:

◆  可以用折半查找方法快速找到关键字,进而找到数据记录的物理地址,实现数据记录的快速查找;

◆ 提供对变长数据记录的便捷访问;

◆ 插入或删除数据记录时不需要移动记录,但需要对索引表进行维护。

缺点:

◆ 索引表中索引项的数目与数据表中记录数相同,当索引表很大时,检索记录需多次访问外存;

◆ 对索引表的维护代价较高,涉及到大量索引项的移动,不适合于插入和删除操作。

树形索引表:

平衡二叉排序树便于动态查找,因此用平衡二叉排序树来组织索引表是一种可行的选择。 R.Bayer和E.Mc Creight在1972年提出了一种多路平衡查找树,称为B_树(其变形体是B+树) 。

B_树设计时主要用于文件系统中,在B_树中,每个结点的大小为一个磁盘页,结点中所包含的关键字及其孩子的数目取决于页的大小。

在实际的文件系统中,基本上不使用B_树,而是使用B_树的一种变体,称为m阶B+树。 它与B_树的主要不同是叶子结点中存储记录。在B+树中,所有的非叶子结点可以看成是索引,而其中的关键字是作为“分界关键字”,用来界定某一关键字的记录所在的子树。一棵m阶B+树与m阶B_树的主要差异是:

⑴ 若一个结点有n棵子树,则必含有n个关键字;

⑵ 所有叶子结点中包含了全部记录的关键字信息以及这些关键字记录的指针,而且叶子结点按关键字的大小从小到大顺序链接;

⑶  所有的非叶子结点可以看成是索引的部分,结点中只含有其子树的根结点中的最大(或最小)关键字。


代码: 

#include <stdio.h>
#include <stdlib.h>
/*#define EQ(a,b) ((a)==(b)) //对数值型关键字比较
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)>(b))*/
typedef int KeyType;
//块内结构
typedef struct RecType{
    KeyType key;
}RecType;
//索引表结构
typedef struct index{
    KeyType maxkey; //块中最大的关键字
    int startpos; //块的起始位置指针
}Index;
//二叉排序树的结点定义
typedef struct Node{
    KeyType key;
    struct Node *Lchild, *Rchild;
}BSTNode;
//二叉排序树的递归查找
BSTNode *BST_Search(BSTNode *T, KeyType key){
    if(T == NULL){
        printf("查找失败");
         return NULL;
    }


    if(T->key == key){

        return T;
    }

    else if(T->key < key)
        return (BST_Search(T->Rchild, key));
    else
        return (BST_Search(T->Lchild, key));

}
//非递归
 BSTNode *BST_Search1(BSTNode *T, KeyType key){
   // BSTNode *p; p = T;
    while(T != NULL && T->key != key){
        if(key > T->key)
            T= T->Rchild;
        else
            T = T->Lchild;
    }
    if(T->key == key)
        return T;
    else
        return NULL;
 }
//索引顺序查找(分块查找)
int Block_search(RecType ST[], Index ind[], KeyType key, int n, int b){
    //在分块索引表中查找关键字为key的记录
    //表长为N, 块数为b

    int i = 1, j;
    //找块
    while((i <= b) && ind[i].maxkey < key){
        i++;
    }
  //  printf("\n i = %d ", i);
    if(i > b){
        printf("没找见1\n");
        return 0;
    }
    //块内找
    j = ind[i].startpos;
 //   printf("\nj = %d", j);
    while((j <= n) && ST[j].key < ind[i].maxkey){
        if(ST[j].key == key)
            break;
        j++;
    }
    if(j > n||ST[j].key != key){
        j = 0;
        printf("没找见2\n");
    }
    return j;
}

//建立ercha排序树
BSTNode *Create_BST(){
    int ch;
    BSTNode *b;
   // printf("先序输入二叉排序树:\n");
    scanf(" %d", &ch);
    if(ch == 0){
        b = NULL;
    }else{
        b = (BSTNode *)malloc(sizeof(BSTNode));
        b->key = ch;
        b->Lchild = Create_BST();
        b->Rchild = Create_BST();

    }
    return b;


}/*
void PerOrderTraverse(BSTNode *bt)
{
    if(bt!=NULL)
   { printf("%d",bt->key);
     PerOrderTraverse(bt->Lchild);
     PerOrderTraverse(bt->Rchild);
   }
}*/
int main()
{
    int b, n, i, m, j;
   /* printf("-----------索引顺序表查找----------\n");

    printf("输入索引表的长度:");
    scanf("%d", &b);
    printf("输入块的大小:");
    scanf("%d", &n);
    RecType ST[n*b];
    Index ind[b];
    printf("建立索引表:\n");
    for(i = 1; i <= b; i++){
        printf("输入索引表的第%d块的最大值:", i);
        scanf("%d", &m);
        ind[i].maxkey = m;
    }
    int a = 1;
    printf("建立块:\n");
    for(i = 1; i <= b; i++){
        ind[i].startpos = a;
        for(j = 0; j < n; j++){
            printf("输入第%d块的第%d个值:", i, j+1);
            scanf("%d", &m);
            ST[a].key = m;
            a++;
        }
    }
    printf("打印索引表:\n");
    for(i = 1; i <= b; i++){
        printf("%d ", ind[i].maxkey);
        printf("%d  \n", ind[i].startpos);
    }
    printf("打印顺序表\n");
    for(i = 1; i <= n*b; i++){
        printf("%d  ", ST[i].key);
    }
    printf("\n");
    printf("输入要查找的值:\n");
    scanf("%d", &m);
    printf("地址为:%d", Block_search(ST, ind, m, n*b, b));*/
    printf("\n\n---------二叉排序树的查找----------\n");
    BSTNode *T;
    BSTNode *p;
    T = Create_BST();
    printf("以%d为根的树创建成功!\n",T->key);
    //PerOrderTraverse(T);
    printf("输入要查找的值:\n");
    scanf("%d", &m);
    printf("递归查找:");
    p = BST_Search(T, m);
    printf("找到了 它的值为%d",p->key);
    if(p->Lchild != NULL)
        printf("左孩子为%d",p->Lchild->key);
    else
        printf("左孩子为空");
    if(p->Rchild != NULL)
        printf("右孩子为%d\n",p->Rchild->key);
    else
        printf("右孩子为空\n");
    // printf("%d \n", p->key);
    printf("非递归查找:");
    p =BST_Search1(T, m);
    printf("找到了 它的值为%d",p->key);
    if(p->Lchild != NULL)
        printf("左孩子为%d",p->Lchild->key);
    else
        printf("左孩子为空");
    if(p->Rchild != NULL)
        printf("右孩子为%d",p->Rchild->key);
    else
        printf("右孩子为空");

  return 0;
}

 结果展示:

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 二叉排序树可以使用顺序或二叉链表作为存储结构进行实现。其中,顺序存储结构需要预先确定二叉树的最大节点数,而二叉链表则不需要。在实现过程中,需要注意保持二叉排序树的有序性,即左子树的所有节点的值均小于根节点的值,右子树的所有节点的值均大于根节点的值。同时,还需要实现插入、删除、查找等基本操作。 ### 回答2: 二叉排序树的实现可以使用顺序或二叉链表作为存储结构。顺序存储结构是将二叉排序树的节点按照某种顺序存储在一维数组中。数组的下标对应节点的位置。通过比较节点的值和数组中的值,可以进行查找、插入和删除等操作。其中,查找操作可以通过二分查找的方式快速定位目标节点。插入操作可以找到插入位置后,将节点的值赋给数组相应位置,然后调整节点的位置以保持二叉排序树的有序性。删除操作会比较复杂一些,需要考虑节点的左右子树情况和后继节点的问题,但同样可以通过数组操作实现。 二叉链表存储结构是使用指针和动态内存分配来实现二叉排序树。每个节点除了存储值之外,还包含指向左右子节点的指针。通过指针的连接,形成一个具有层次和有序性的二叉排序树查找、插入和删除操作可以通过递归或循环实现。对于查找操作,根据节点值与目标值的大小关系可以选择向左或向右子树递归查找,直到找到目标节点或遍历到叶子节点。插入操作会不断比较节点值与目标值的大小关系,找到合适的位置后动态分配内存并链接节点。删除操作也会涉及到节点的链接断开和内存释放等操作。 无论是顺序存储结构还是二叉链表存储结构,实现二叉排序树都需要考虑平衡性和旋转等问题,以保证树的查找性能和有序性。同时,根据具体的应用场景和需求,可以选择适合的存储结构和实现方法来构建和操作二叉排序树。 ### 回答3: 二叉排序树(Binary Search Tree,BST)可以使用顺序存储结构或者二叉链表来实现。 顺序存储结构是将BST的节点按照一定规则存储在一维数组中。具体实现时,可以使用一个固定大小的数组,且数组的索引表示节点的值,数组的元素表示节点的状态(空节点或非空节点)。在顺序存储结构中,根节点存储在数组的中间位置,左子节点存储在数组的左侧位置,右子节点存储在数组的右侧位置。该实现方式方便查找和插入元素,但在删除元素时会涉及到节点的移动和重新排序,可能会导致数组长度的变化。 二叉链表是每个节点通过指针连接形成的链表结构。每个节点包含一个数据项,以及左子节点和右子节点的指针。通过指针的链接,可以方便地访问和操作节点,实现BST的各种操作。在二叉链表实现中,根节点作为链表的头节点。这种实现方式比较灵活,可以动态地调整树的结构,但相比顺序存储结构,需要更多的内存空间。 无论选择哪种存储结构,实现BST的基本操作都是一样的,包括查找、插入和删除等。每个操作都需要考虑保持二叉排序树的特性,即左子节点的值小于等于父节点的值,右子节点的值大于等于父节点的值。无论是顺序存储结构还是二叉链表,都可以满足这个特性。 在实际应用中,根据具体情况选择不同的存储结构。顺序存储结构适用于数据量较小且不需要频繁修改的场景,而二叉链表适用于数据量较大或者需要频繁修改的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值