#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100 /*顺序表的表长*/
typedef int KeyType; /*关键字类型为 int 型*/
typedef struct {
KeyType key; /*存放关键字,KeyType 为关键字类型*/
} SearchL;
int SeqSearch(SearchL r[], int n, KeyType k) { /*顺序查找算法函数,表中元素下标为 1 到 n*/
int i = n;
r[0].key = k; /*设元素 r[o]为要查找的关键字 k(即监视哨)*/
while (r[i].key != k) /*从后向前顺序比较*/
i--;
return i; /*返回查找元素下标,当为 0 时表示查找失败*/
}
int BinSearch(SearchL r[], int n, KeyType k) { /*折半查找算法函数,表中元素下标为 1 到 n*/
int low, high, mid;
low = 1; high = n; /*置区间初值*/
while (low <= high) /*查找区间不为空时*/
{ mid = (low + high) / 2;
if (k == r[mid].key)
return mid; /*找到待查元素*/
else if (k < r[mid].key)
high = mid - 1; /*未找到,继续在前半区间进行查找*/
else
low = mid + 1; /*未找到,继续在后半区间进行查找*/
}
return 0;
}
typedef struct { /*分块查找的索引表类型*/
KeyType key; /*关键字*/
int low, high; /*每块的低、高地址*/
} IdxType;
void CreatIdx(SearchL r[], IdxType idx[], int m, int n)
{
int i, j, k = 0;
KeyType max;
for (i = 0; i < m; i += n)
{
max = r[i].key;
for (j = i + 1; j < i + n && j < m; j++)
{
if (r[j].key > max)
max = r[j].key;
}
idx[k].key = max;
idx[k].low = i;
if (i + n - 1 <= m - 1)
idx[k].high = i + n - 1;
else
idx[k].high = m - 1;
k++;
}
}
int BlkSearch(SearchL r[], IdxType idx[], int m, KeyType k) {
int low, high, mid, i, j, find = 0;
i = 0;
while (idx[i].key < k) { // 当索引表的关键字小于查找关键字 k 时,在索引表中定位
i++;
}
low = idx[i].low; high = idx[i].high;
while (low <= high && !find) { // 当在索引表中找到该元素所在块时
mid = (low + high) / 2; // 在该索引表内进行折半查找
if (k < idx[mid].key) {
high = mid - 1;
} else if (k > idx[mid].key) {
low = mid + 1;
} else { // 当找到关键字 k 时
high = mid - 1;
find = 1;
}
}
if (low < m) { // 当在索引表中有该元素所在块时
i = idx[low].low; // i 赋为索引表该块的低地址
j = idx[low].high; // j 赋为索引表该块的高地址
}
while (i < j && r[i].key != k) { // 在顺序表的这个块内进行顺序查找
i++;
}
if (i >= j) { // 当没找到时返回-1
return -1;
} else { // 当找到时返回下标值 i
return i;
}
}
typedef struct treenode { // 二叉排序树的结点类型
KeyType key; // 关键字
struct treenode *lchild, *rchild; // 左、右孩子指针
} BTNode;
BTNode *BSTInsert(BTNode *bt, KeyType k) { // 二叉排序树的元素插入函数
BTNode *f, *p = bt; // p 指针指向二叉排序树的根结点
while (p != NULL) { // 当 p 指针不为空时,由指针 f 确定插入位置的双亲结点
f = p; // 指针 f 指向指针 p 所指结点
if (p->key > k) { // 当 p 所指结点的关键字大于插入值时
p = p->lchild; // p 移到它的左孩子结点上
} else {
p = p->rchild; // p 移到它的右孩子结点上
}
}
p = (BTNode *)malloc(sizeof(BTNode)); // 建立新结点
p->key = k; // 将关键字 k 存入新结点的数据域
p->lchild = p->rchild = NULL; // 左、右孩子指针设为空
if (bt == NULL) { // 二叉树为空树时,新建结点作为二叉排序树的根结点
bt = p;
} else if (k < f->key) { // 若插入关键字 k 小于其双亲结点关键字,则插入为双亲结点的左孩子
f->lchild = p;
} else { // 若插入关键字 k 大于其双亲结点关键字,则插入为双亲结点的右孩子
f->rchild = p;
}
return bt; // 返回根节点指针
}
BTNode *CreateBST(KeyType str[], int n) { /*建立二叉排序树函数*/
int i = 0;
BTNode *bt = NULL; /*初始化根结点为空*/
while (i < n) { /*当建立没结束时*/
bt = BSTInsert(bt, str[i]); /*将第 i 个元素插入到二叉排序树中*/
i++;
}
return bt; /*返回根结点指针*/
}
void DispBStree(BTNode *bt) { /*用广义表显示二叉排序树函数*/
if (bt != NULL) {
printf("%d", bt->key); /*输出根结点的关键字*/
if (bt->lchild != NULL || bt->rchild != NULL) { /*当根结点的左、右孩子指针不为空时*/
printf("("); /*输出左括号*/
DispBStree(bt->lchild); /*输出该结点的左孩子*/
if (bt->rchild != NULL) /*若其右指针不为空时*/
printf(","); /*输出逗号*/
DispBStree(bt->rchild); /*输出该结点的右孩子*/
printf(")"); /*输出右括号*/
}
}
}
BTNode *BSTDelete(BTNode *bt, KeyType k) {
BTNode *p, *f, *s, *q;
p = bt;
f = NULL;
while (p) {
if (p->key == k) break;
f = p;
if (p->key > k)
p = p->lchild;
else
p = p->rchild;
}
if (p == NULL) return bt;
if (p->lchild == NULL) {
if (f == NULL) {
bt = p->rchild;
} else if (f->lchild == p) {
f->lchild = p->rchild;
} else {
f->rchild = p->rchild;
}
free(p);
} else {
q = p;
s = p->lchild;
while (s->rchild) {
q = s;
s = s->rchild;
}
if (q == p) q->lchild = s->lchild;
else q->rchild = s->lchild;
p->key = s->key;
free(s);
}
return bt;
}
BTNode *BSTSearch(BTNode *bt, KeyType k) {
/* 二叉排序树的元素查找函数 */
if (bt == NULL) {
return NULL; /* 空树则返回空指针 */
} else {
if (k == bt->key) {
return bt; /* 关键字 k 等于根结点关键字,返回根结点指针 */
} else if (k < bt->key) {
return BSTSearch(bt->lchild, k); /* 关键字 k 小于根结点关键字,到根结点的左子树查找 */
} else {
return BSTSearch(bt->rchild, k); /* 关键字 k 大于根结点关键字,到根结点的右子树查找 */
}
}
}
void MenuBTree() {
/* 显示二叉排序树子菜单函数 */
printf("\n 二叉排序树 ");
printf("\n===========================================");
printf("\n| 1------建立二叉排序树 |");
printf("\n| 2------插入一个元素 |");
printf("\n| 3------删除一个元素 |");
printf("\n| 4------查找一个元素 |");
printf("\n| 0------返回 |");
printf("\n===========================================");
printf("\n 请输入序号(0-4)选择要进行的操作:");
}
void BTFun() {
/* 二叉排序树子函数 */
KeyType str[100];
BTNode *bt;
int i, n, x, menux;
MenuBTree();
scanf("%d", &menux);
do {
switch (menux) { /* 判断进行何种操作 */
case 1: /* 建立二叉排序树 */
printf("请输入要生成二叉排序树的关键字的个数:");
scanf("%d", &n);
printf("请输入二叉排序树的各个关键字:");
for (i = 0; i < n; i++) {
scanf("%d", &str[i]);
}
bt = CreateBST(str, n);
printf("建立的二叉排序树广义表表示法为:");
DispBStree(bt);
break;
case 2: /* 在二叉排序树中插入一个元素 */
printf("请输入要插入的元素值: ");
scanf("%d", &x);
bt = BSTInsert(bt, x);
printf("插入后的二叉排序树为:");
DispBStree(bt);
break;
case 3: /* 在二叉排序树中删除一个元素 */
printf("请输入要删除的元素:");
scanf("%d", &x);
bt = BSTDelete(bt, x);
printf("删除元素%d 后的二叉排序树为:", x);
DispBStree(bt);
break;
case 4: /* 在二叉排序树中查找某元素 */
printf("请输入查找的元素值:");
scanf("%d", &x);
if ((BSTSearch(bt, x)) != NULL) {
printf("在二叉排序树中存在元素%d!", x);
} else {
printf("在二叉排序树中不存在元素%d!", x);
}
break;
case 0:
return;
break;
default:
printf("输入选项错误,请重新输入(0-4)!");
}
MenuBTree();
scanf("%d", &menux);
} while (1);
}
void Menu() {
/* 显示菜单子函数 */
printf("\n 查找子系统");
printf("\n==========================================");
printf("\n| 1——顺序查找 |");
printf("\n| 2——折半查找 |");
printf("\n| 3——分块查找 |");
printf("\n| 4——二叉排序树查找 |");
printf("\n| 0——返回 |");
printf("\n==========================================");
printf("\n 请输入菜单号(0-4):");
}
main() {
SearchL r[MAXSIZE];
IdxType idx[MAXSIZE];
int i, m, n, x, k, address;
char ch1, ch2, a;
ch1 = 'y';
while (ch1 == 'y' || ch1 == 'Y') {
Menu();
scanf("%c", &ch2);
getchar();
switch (ch2) {
case '1':
printf("请输入表的元素个数(0-%d):", MAXSIZE-1);
scanf("%d", &n);
printf("请输入%d 个表中的关键字(整数):", n);
for (i = 1; i <= n; i++) {
scanf("%d", &r[i].key);
}
printf("请输入要查找的关键字:");
scanf("%d", &x);
if ((address = SeqSearch(r, n, x)) != 0) {
printf("该元素在表中的位置为:%d", address);
} else {
printf("该元素不在表中!");
}
break;
case '2':
printf("请输入表的元素个数(0-%d):", MAXSIZE-1);
scanf("%d", &n);
printf("请按照从小到大的顺序输入%d 个关键字(为整数):", n);
for (i = 1; i <= n; i++) {
scanf("%d", &r[i].key);
}
printf("请输入要查找的关键字:");
scanf("%d", &x);
if ((address = BinSearch(r, n, x)) != 0) {
printf("该元素在表中的位置为:%d", address);
} else {
printf("该元素不在该有序表中!");
}
break;
case '3':
printf("请输入表的元素个数(0-%d):", MAXSIZE-1);
scanf("%d", &m);
printf("请输入表中的关键字(为整数),要求块内无序,块间有序:\n");
for(i=0; i<m; i++)
scanf("%d", &r[i].key);
printf("表输入索引表每块的大小:");
scanf("%d", &n);
CreatIdx(r, idx, m, n);
printf("\n建立的顺序表为:\n");
for(i=0; i<m; i++)
printf("%6d", r[i].key);
printf("\n索引表信息如下:\n");
printf("低地址\t高地址\t最大关键字\n");
if(m%n==0)
for(i=0; i<m/n; i++)
printf("%5d\t%5d\t%5d\n", idx[i].low, idx[i].high, idx[i].key);
else
for(i=0; i<m/n+1; i++)
printf("%5d\t%5d\t%5d\n", idx[i].low, idx[i].high, idx[i].key);
printf("请输入要查找的元素的关键字:");
scanf("%d", &k);
if((address=BlkSearch(r, idx, 3, k))!=-1)
printf("该元素在表中的位置为:%d", address+1);
else
printf("该元素不在表中!");
break;
case '4':
BTFun();
break;
case '0':
ch1='n';
break;
default:
printf("输入有误,请输入 0-9 进行选择!");
}
}
}