索引順序表查詢和二叉排序樹查詢
二叉排序樹(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+樹
⑴ 若一個結點有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;
}
結果展示: