关闭

查找(二)动态表查找

标签: 二叉排序树键树B-树平衡二叉树
255人阅读 评论(0) 收藏 举报
分类:

动态表查找的特点是:表结构本身在查找过程中动态生成。
包括:
二叉排序树(BinarySortTree)或二叉搜索树(BinarySearchTree),平衡二叉树、B-树和B+树,键树

1.二叉排序树

BinarySortTree

2.平衡二叉树

AVL Tree

3.B-树

//B-Tree.c

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

#define TRUE 1
#define FALSE 0
#define m 3 //定义B-树的阶数
typedef int Boolean;
typedef int KeyType;    //定义关键字类型
typedef char InfoType;  //定义记录中除关键字外其它数据的类型
typedef struct {        //定义记录类型
    KeyType key;
    InfoType otherinfo;
}RedType;
typedef struct BTNode{  //定义B-树中结点类型(非叶子结点)
    int keynum;//结点中关键字个数
    struct BTNode *parent;//指向双亲结点
    KeyType key[m + 1];//定义关键字向量,0号单元未用
    struct BTNode *ptr[m + 1];//子树指针向量
    RedType *recptr[m + 1];//记录指针向量,0号单元未用
}BTNode, *BTree;
typedef struct{//定义B-树查找结果类型
    BTNode *pt;//指向找到的结点
    int i;//1...m,在结点中的关键字序号
    int tag;//1:查找成功,0:查找失败
}Result;



//此函数用来在B-树中查找关键字key
Result SearchBTree(BTree T, KeyType key){
    //在m阶B-树T上查找关键字key,返回结果Result。
    //若查找成功,则特征值tag=1,指针pt所指结点中第i个关键字等于key;
    //若查找失败,则特征值tag=0,等于key的关键字应插在指针pt所指结点中第i和第i+1个关键字之间。
    int i=0;
    Boolean found=FALSE;
    BTree p, q;
    Result result;
    p = T;  //p指向待查结点
    q = NULL;   //q指向p的双亲

    while (p&&!found){
        i = Search(p, key);//在p->key[1...keynum]中查找,i使得p->key[i]<=key<p->key[i+1]
        if (i > 0 && p->key[i] == key)
            found = TRUE;//找到待查关键字
        else{
            q = p;
            p = p->ptr[i];
        }

        if (found){
            result.pt = p;
            result.i = i;
            result.tag = 1;

            return result;
        }
        else{
            result.pt = q;
            result.i = i;
            result.tag = 0;

            return result;
        }
    }

}

// 此函数在B-树上插入一个关键字
Boolean InsertBTree(BTree T, KeyType key, BTree q, int i){
    //在m阶B-树T上结点*q的key[i]与key[i+1]之间插入关键字key
    //若引起结点过大,则沿双亲链进行必要的结点分裂调整,使T仍是m阶B-树

    KeyType x = key;    //x进行关键字的迭代
    BTree ap = NULL;    //ap指向新结点
    Boolean finished = FALSE;   //标识是否插入完成
    int s;//数组下标
    while (q&&!finished){
        Insert(q, i, x, ap);//将x和ap分别插入到q->key[i+1]和q->ptr[i+1]
        if (q->keynum < m)
            finished = TRUE;//插入完成
        else{
            s = floor(m / 2);
            split(q, s, ap);
            x = q->key[s];
            /*
            (此处过程omit)
            将q->key[s+1...m],q->ptr[s...m]和q->recptr[s+1...m]移入新结点*ap
            */
            q = q->parent;//q上移到双亲结点
            if (q){
                i = Search(q, x);//在双亲结点*q中查找x的插入位置
            }
        }
    }
    if (!finished)  //T是空树(参数q初值为NULL)或者根结点已分裂为结点*q和*ap
        NewRoot(T, q, x, ap);//生成含信息(T,x,ap)的新结点*T,原T和ap为子树指针

    return TRUE;
}

4.键树

键树又称数字查找树(Digital Search Trees)。
键树有两种存储结构:
(1)双链树
(2)多重链表键树。(Trie Tree)

(1)双链树

//双链树
#include <stdio.h>
#include <stdlib.h>

#define MAXKEYLEN 16    //定义关键字最大长度
typedef struct{ //关键字类型
    char ch[MAXKEYLEN]; //关键字
    int num;    //关键字长度
}KeyType;
typedef enum{ LEAF, BRANCH } NodeKind;  //结点种类:叶子,分支
typedef char InfoType;  //定义记录中除关键字外其它数据的类型
typedef struct {        //定义记录类型
    KeyType key;
    InfoType otherinfo;
}RedType;
typedef struct DLTNode{ //定义双链树结点类型 
    char symbol;
    struct DLTNode *next;   //指向兄弟结点的指针
    NodeKind kind;
    union {
        RedType *infoptr;   //叶子结点的记录指针
        struct DLTNode *first;  //分支结点的记录指针
    };
}DLTNode, *DLTree;


//在双链树中查找记录
RedType *SearchDLTree(DLTree T, KeyType key){
    //在非空双链树T中查找关键字等于key的记录。若存在,则返回指向该记录的指针,否则返回空指针。
    DLTree p;
    p = T->first;
    int i = 0;
    while (p&&i<key.num){
        while (p&&p->symbol != key.ch[i])//查找关键字的第i位
            p = p->next;
        if (p&&i < key.num - 1)//准备查找下一位
            p = p->first;
        i++;
    }
    if (!p) 
        return NULL;    //查找不成功,返回NULL
    else 
        return p->infoptr;//查找成功,返回指向该记录的指针
}

(2)Trie 树

//TrieTree.c

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

#define MAXKEYLEN 16    //定义关键字最大长度
typedef struct{ //关键字类型
    char ch[MAXKEYLEN]; //关键字
    int num;    //关键字长度
}KeyType;
typedef enum{ LEAF, BRANCH } NodeKind;  //结点种类:叶子,分支
typedef char InfoType;  //定义记录中除关键字外其它数据的类型
typedef struct {        //定义记录类型
    KeyType key;
    InfoType otherinfo;
}RedType;
typedef struct TrieNode{//Trie树结点类型定义
    NodeKind kind;
    union{
        struct {
            KeyType key;
            RedType *infoptr;
        }leaf;//叶子结点
        struct {
            TrieNode *ptr[27];
            int num;
        }branch;//分支结点
    };
}TrieNode, *TrieTree;


//此函数在Trie Tree中查找等于关键字key的记录
RedType *SearchTrie(TrieTree T, KeyType key){
    TrieTree p;
    int i = 0;
    for (p = T, i = 0; p && p->kind == BRANCH && i < key.num; i++)//对key的每个字符逐个查找
        p = p->branch.ptr[ord(key.ch[i])];//ord()函数求字符在字母表中的序号
    if (p && p->kind == LEAF && p->leaf.key == key)//查找成功
        return p->leaf.infoptr;
    else 
        return NULL;

}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:131729次
    • 积分:4030
    • 等级:
    • 排名:第8093名
    • 原创:272篇
    • 转载:39篇
    • 译文:0篇
    • 评论:8条
    最新评论