1 作业题目
9.1 已知如下所示长度为12的表
(Jan,Feb,Mar,Apr,May,June,July,Aug,Sep,Oct,Nov,Dec)
(1) 试按表中元素的顺序依次插入一棵初始为空的二叉排序树,画出插入完成后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
(2) 若对表中元素先进行排序构成有序表,求在等概率情况下对此有序表进行折半查找时查找成功的平均查找长度。2
(3) 按表中元素顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
9.2 试从空树开始,画出按以下次序向2-3树即3阶B-树中插入关键码的建树过程:20、30、50、52、60、68、70,如果此后删除50和68,画出每一步执行后2-3树的状态。
9.3 选取哈希函数H(k)=(3k) MOD 11。用开放定址法处理冲突,di=i ((7k) MOD 10 +1) (i=1,2,3…)。试在0—10的散列地址空间中对关键字序列(22、41、53、46、30、13、01、67)构造哈希表,并求等概率情况下查找成功时的平均查找长度。
9.4 试为下列关键字建立一个装载因子不小于0.75的哈希表,并计算你所构造的哈希表的平均查找长度。(ZHAO 、QIAN、SUN、LI、ZHOU、WU、ZHANG、WANG、CHANG、CHAO、YANG、JIN)
9.5 在地址空间为0—16的散列区中,对以下关键字序列构造两个哈希表:
(Jan,Feb,Mar,Apr,May,June,July,Aug,Sep,Oct,Nov,Dec)
(1)用线性探测开放定址法处理冲突
(2)用链地址法处理
并分别求这两个哈希表在等概率情况下查找成功和不成功时的平均查找长度。设哈希函数为H(x)= i/2 ,其中i为关键字中第一个字母在字母表中的序号。
9.6 设计一个读入一串整数构成一颗二叉排序树的程序,从二叉排序树中删除一个结点,使该二叉树仍保持二叉排序树的特性。
9.7 设定哈希函数 H(key) = key MOD 11 ( 表长=11 ),输入一组关键字序列,根据线性探测再散列解决冲突的方法建立哈希表的存储结构,显示哈希表,任意输入关键字,判断是否在哈希表中。
2 作业题目解答
【9.1题解答】
(1) 试按表中元素的顺序依次插入一棵初始为空的二叉排序树,画出插入完成后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度
(2) 若对表中元素先进行排序构成有序表,求在等概率情况下对此有序表进行折半查找时查找成功的平均查找长度
(3) 按表中元素顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
【9.2题解答】
【9.3题解答】
【9.4题解答】
【9.5题解答】
(1)用线性探测开放定址法处理冲突
(2)用链地址法处理
【9.6题解答】
算法思路:
插入函数,按照大小先去寻找结点应该插入的位置,再对结点经行增加,并且和其他结点构建连接关系。
删除函数:现找到要删除结点的位置,分3种情况判断,右子树空、左子树空、左右都不空,分别处理每种情况的连接关系。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define ENDKEY 0
typedef int KeyType;
typedef struct node
{
KeyType key; /*关键字的值*/
struct node* lchild, * rchild;/*左右指针*/
}BSTNode, * BSTree;
int InsertBST(BSTree* bst, KeyType key)
/*若在二叉排序树中不存在关键字等于key的元素,插入该元素*/
{
BSTree s;
if (*bst == NULL)
{
s = (BSTree)malloc(sizeof(BSTNode));
s->key = key;
s->lchild = NULL;
s->rchild = NULL;
*bst = s;
}
else if (key < (*bst)->key)
InsertBST(&((*bst)->lchild), key);
else if (key > (*bst)->key)
InsertBST(&((*bst)->rchild), key);
return 0;
}
void CreateBST(BSTree* bst)
/*从键盘输入元素的值,创建相应的二叉排序树*/
{
KeyType key;
*bst = NULL;
scanf("%d", &key);
while (key != ENDKEY)
{
InsertBST(bst, key);
scanf("%d", &key);
}
}
void InOrder(BSTree bst)
/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
//printf("采用中序遍历二叉树输出\n");
if (bst != NULL)
{
InOrder(bst->lchild); /*中序遍历左子树*/
printf("%d->", bst->key); /*访问根结点*/
InOrder(bst->rchild); /*中序遍历右子树*/
}
}
BSTree SearchBST(BSTree bst, KeyType key)
/*在根指针bst所指二叉排序树中,递归查找某关键字等于key的元素,若查找成功,返回指向该元素结点指针,否则返回空指针*/
{
if (!bst)
return NULL;
else if (bst->key == key)
return bst;
else if (bst->key > key)
return SearchBST(bst->lchild, key);
else
return SearchBST(bst->rchild, key);
//请完成本函数的功能
}
int DelBST(BSTree t, KeyType k) /*在二叉排序树t中删去关键字为k的结点*/
{
BSTNode* p, * f, * s, * q;
p = t;
f = NULL;
while (p) /*查找关键字为k的待删结点p*/
{
if (p->key == k) break; /*找到则跳出循环*/
f = p; /*f指向p结点的双亲结点*/
if (p->key > k)
p = p->lchild;
else
p = p->rchild;
}
if (p == NULL) return 0; /*若找不到,返回原来的二叉排序树*/
if (p->lchild == NULL) /*p无左子树*/
{
if (f == NULL)
t = p->rchild; /*p是原二叉排序树的根*/
else
if (f->lchild == p) /*p是f的左孩子*/
f->lchild = p->rchild; /*将p的右子树链到f的左链上*/
else /*p是f的右孩子*/
f->rchild = p->rchild; /*将p的右子树链到f的右链上*/
free(p); /*释放被删除的结点p*/
}
else /*p有左子树*/
{
q = p;
s = p->lchild;
while (s->rchild) /*在p的左子树中查找最右下结点*/
{
q = s;
s = s->rchild;
}
if (q == p)
q->lchild = s->lchild; /*将s的左子树链到q上*/
else
q->rchild = s->lchild;
p->key = s->key; /*将s的值赋给p*/
free(s);
}
return 1;
} /*DelBST*/
void main()
{
BSTree T, p;
int keyword, temp;
char ch, j = 'y';
T = NULL;
while (j != 'n')
{
printf("1.创建二叉排序树\n");
printf("2.显示排序的数据(中序遍历输出)\n");
//printf("3.查找数据\n");
//printf("4.在查找树中插入一个数据\n");
printf("3.在查找树中删除一个数据\n");
printf("4.程序结束,退出\n");
scanf(" %c", &ch); //输入操作选项
switch (ch)
{
case '1':
printf("请输入数据,以0作为数据输入结束。\n");
CreateBST(&T);
break;
case '2':
if (!T) printf("二叉排序树中没有数据。\n");
else { InOrder(T); printf("\b\b \n"); }
break;
//case '3':
// printf("输入待查找的数据值:\n");
// scanf("%d", &keyword); //输入要查找元素的关键字
// p = SearchBST(T, keyword);
// if (!p) printf("%d 没有找到。\n", keyword); //没有找到
// else printf("%d 查找成功。\n", keyword); //成功找到
// break;
//case '4':
// printf("输入待插入的数据:");
// scanf("%d", &keyword); //输入要插入元素的关键字
// temp = InsertBST(&T, keyword);
// if (temp == FALSE)
// printf("%d 已在二叉树中!\n", keyword); //该元素已经存在
// else
// printf("%d 插入成功!\n", keyword);
// break;
case '3':
printf("输入待删除的数据:");
scanf("%d", &keyword); //输入要删除元素的关键字
temp = DelBST(T, keyword);
if (temp == FALSE) printf("%d 不存在!\n", keyword); //该元素不存在
else printf("成功删除%d\n", keyword); //成功删除
break;
default:
j = 'n';
}
}
printf("程序结束!\n");
}
运行结果:
【9.7题解答】
算法思路:
插入函数:计算每个值对应的哈希地址,如果冲突经行线性探测,直到不冲突为止。
查找函数:先计算该值对应的哈希地址,如果该地址上的值不等于这个数,就线性探测的往下找,找到则返回成果。如果一直往下找,碰到一个地址上没有存任何值,则证明该数不存在哈希表中。
#include <stdio.h>
int main() {
//功能描述:在哈希表中插入值,对于冲突的地址用线性探测
int Hash[11] = { 0 };
printf("输入需要插入哈希表的个数:");
int n;
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
printf("插入第%d个数:", i + 1);
int a;
scanf_s("%d", &a);
int pos = a % 11;
int d = 1;
while (Hash[pos] != 0) {
d = 1;
pos = (pos + d) % 11;
//d++;
}
Hash[pos] = a;
printf("第%d个数的哈希地址是%d\n", i + 1, pos);
}
//功能描述:查找某数是否在哈希表中
printf("\n");
printf("\n");
printf("输入需要查找的个数:");
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
printf("输入需要查找的数:");
int a;
scanf_s("%d", &a);
int pos = a % 11;
int flag = 0;
while (Hash[pos] != 0) {
if (Hash[pos] == a) {
printf("此数存在于哈希中\n");
flag = 1;
break;
}
pos++;
pos % 11;
}
if (flag == 0) printf("此数不存在于哈希中\n");
}
}
运行结果: