习题1
试写出折半查找的递归算法。
c
#include <stdio.h>
#include <stdlib.h>
#define Maxsize 100
typedef int KeyType;
typedef char InfoType;
typedef struct
{
KeyType Key;
InfoType OtherInfo;
}elem;
typedef struct
{
elem *R;
int length;
}SSTable;
void initSSTable(SSTable& ST);
int Search_Bin(SSTable ST, KeyType key, int low, int high);
int main()
{
SSTable ST = { NULL,0 };
int i = 0;
KeyType key = 0;
int r = 0;
char choice = '\0';
initSSTable(ST);
printf("请输入递增有序表中元素的个数:");
scanf_s(" %d", &ST.length);
for (i = 1; i <= ST.length; i++)
{
printf("请输入第%d个元素的值:", i);
scanf_s(" %d", &ST.R[i].Key);
}
while (1)
{
printf("\n请输入要查找到数:");
scanf_s(" %d", &key);
r = Search_Bin(ST, key, 1, ST.length);
if (r == -1)
{
printf("%d查找失败。\n",key);
}
else
{
printf("%d的位置为:%d\n", key, r);
}
printf("是否继续?(y/Y)");
scanf_s(" %c", &choice);
if (choice != 'y' && choice != 'Y')
{
break;
}
}
return 0;
}
void initSSTable(SSTable& ST)
{
ST.R = (elem*)malloc(sizeof(elem)* Maxsize);
ST.length = 0;
}
//折半查找 递归
int Search_Bin(SSTable ST, KeyType key, int low, int high)
{
if (low > high)
{
return -1;
}
int mid = (low + high) / 2;
if (key == ST.R[mid].Key)
{
return mid;
}
else if (key > ST.R[mid].Key)
{
return Search_Bin(ST, key, mid + 1, high);
}
else
{
return Search_Bin(ST, key, low, mid - 1);
}
}
习题2
试写一个判别给定二叉树是否为二叉排序树的算法。
c
#include <stdio.h>
#include <stdlib.h>
typedef int KeyType;
typedef char InfoType;
typedef struct
{
KeyType Key;
InfoType OtherInfo;
}ElemType;
typedef struct BTNode
{
ElemType data;
struct BTNode* lchild;
struct BTNode* rchild;
}BTNode,* BTree;
#define true 1
#define false 0
bool flag = true; //全局变量,初值为true. 若非二叉排序树,则置flag为false.
BTree pre = NULL;
void initTree(BTree& T);
void CreateTree(BTree& T);
void JudgeBSTree(BTree T, bool& flag);
int main()
{
BTree T = NULL;
initTree(T);
CreateTree(T);
JudgeBSTree(T, flag);
if (flag == 1)
{
printf("该二叉树为排序二叉树。\n");
}
else
{
printf("该二叉树为非排序二叉树。\n");
}
return 0;
}
void initTree(BTree& T)
{
T = NULL;
}
//创建普通二叉树
void CreateTree(BTree& T)
{
ElemType e = { 0,'\0' };
printf("请输入结点的关键字域值(结点不存在时,输入0):");
scanf_s(" %d", &e.Key);
if (e.Key == 0)
{
T = NULL;
}
else if (e.Key != 0)
{
T = (BTree)malloc(sizeof(BTNode));
T->data = e;
CreateTree(T->lchild);
CreateTree(T->rchild);
}
}
//中序遍历输入的二叉树,判断是否递增
void JudgeBSTree(BTree T, bool& flag)
{
if (T && flag)
{
JudgeBSTree(T->lchild, flag);
//就是将原来中序遍历输出根结点的命令,替换为将该根结点值与其前一个值相比较
if (pre == NULL)
{
pre = T; //pre只有在中序遍历到第一个结点时为空,后面的结点都不为空。而第一个结点不必判断。
}
else if (pre->data.Key < T->data.Key) //每一个中序遍历的结点值T->data.Key都需要比前面一个结点值pre->data.Key大
{
pre = T;
}
else
{
flag = false;
}
JudgeBSTree(T->rchild, flag);
}
}
c
//中序遍历输入的二叉树,判断是否递增
void JudgeBSTree(BTree T, bool &flag)
{
if (T)
{
printf("\n\n【a】T->data.Key = %d", T->data.Key);
if (T->lchild)
{
printf("\n【a】T->lchild->data.Key = %d", T->lchild->data.Key);
}
else
{
printf("\n【a】T->lchild->data.Key = #");
}
if (T->rchild)
{
printf("\n【a】T->rchild->data.Key = %d", T->rchild->data.Key);
}
else
{
printf("\n【a】T->rchild->data.Key = #");
}
}
else
{
printf("\n\n【a】T->data.Key = #");
}
if (T)
{
printf("\n【1】开始 T = %d\n", T->data.Key);
}
else
{
printf("\n【1】开始 T = #\n");
}
if (T && flag)
{
if (T->lchild)
{
printf("\n【2】开始%d->lchild = %d \n", T->data.Key, T->lchild->data.Key);
}
else
{
printf("\n【2】开始%d->lchild = # \n ", T->data.Key);
}
JudgeBSTree(T->lchild,flag);
if (T->lchild)
{
printf("\n【3】%d->lchild = %d 结束\n", T->data.Key, T->lchild->data.Key);
}
else
{
printf("\n【3】%d->lchild = # 结束\n ", T->data.Key);
}
if (pre)
{
printf("\n\n【b】pre->data.Key = %d \n", pre->data.Key);
}
else
{
printf("\n\n【b】pre->data.Key = # \n");
}
//就是将原来中序遍历输出根结点的命令,替换为将该根结点值与其前一个值相比较
if (pre == NULL)
{
pre = T; //pre只有在中序遍历到第一个结点时为空,后面的结点都不为空。而第一个结点不必判断。
}
else if(pre->data.Key < T->data.Key) //每一个中序遍历的结点值T->data.Key都需要比前面一个结点值pre->data.Key大
{
pre = T;
}
else
{
flag = false;
}
if (T->rchild)
{
printf("\n【4】开始%d->rchild = %d \n", T->data.Key, T->rchild->data.Key);
}
else
{
printf("\n【4】开始%d->rchild = # \n ", T->data.Key);
}
JudgeBSTree(T->rchild, flag);
if (T->rchild)
{
printf("\n【5】%d->rchild = %d 结束\n", T->data.Key, T->rchild->data.Key);
}
else
{
printf("\n【5】%d->rchild = # 结束\n ", T->data.Key);
}
}
if (T)
{
printf("\n【6】T = %d 结束 \n", T->data.Key);
}
else
{
printf("\n【6】T = # 结束\n");
}
}
习题3
已知二叉排序树采用二叉链表存储结构,根结点的指针为 T, 链结点的结构为 (lchild,data, rchild) , 其中lchild、rchild分别指向该结点左、右孩子的指针,data域存放结点的数据信息。
请写出递归算法,从小到大输出二叉排序树中所有数据值 ≥ x 的结点的数据。要求先找到第一个满足条件的结点后,再依次输出其他满足条件的结点。
【在中序遍历时判断】
c
#include <stdio.h>
#include <stdlib.h>
#define ENDFLAG -1 //自定义常量,作为输入结束标志
typedef int KeyType;
typedef char InfoType;
//二叉排序树的二叉链表存储表示
typedef struct
{
KeyType Key;
InfoType otherinfo;
}ElemType;
typedef struct BSTNode
{
ElemType data;
struct BSTNode* lchild;
struct BSTNode* rchild;
}BSTNode, * BSTree;
void InitBiTree(BSTree& T);
void InsertBST(BSTree& T, ElemType e);
void CreateBST(BSTree& T);
void preOrderTraverse(BSTree T);
void InOrderTraverse(BSTree T);
void posOrderTraverse(BSTree T);
void Judge_x(BSTree T, int x);
int main()
{
BSTree T = NULL;
InitBiTree(T);
CreateBST(T);
printf("\n二叉排序树链表的先序序列为: ");
preOrderTraverse(T);
printf("\n二叉排序树链表的中序序列为: ");
InOrderTraverse(T);
printf("\n二叉排序树链表的后序序列为: ");
posOrderTraverse(T);
printf("\n≥50的关键字为:");
Judge_x(T, 50);
return 0;
}
//初始化二叉排序树
void InitBiTree(BSTree& T)
{
T = NULL;
}
//算法 7.5 二叉排序树的插入
//前提:当二叉排序树T中不存在关键字等于e.key的数据元素时, 则插入该元素
void InsertBST(BSTree& T, ElemType e)
{
if (!T)
{
BSTree S = (BSTree)malloc(sizeof(BSTNode));
S->data = e;
S->lchild = NULL;
S->rchild = NULL;
T = S; //把新结点*S链接到已找到的插入位置
}
else if (e.Key < T->data.Key)
{
InsertBST(T->lchild, e);
}
else if (e.Key > T->data.Key)
{
InsertBST(T->rchild, e);
}
else
{
printf("当二叉排序树T中存在关键字等于%d的结点,无法插入。\n", e.Key);
return;
}
}
//算法7.6 二叉排序树的创建(在插入操作的基础上,且是从空的二叉排序树开始的)
//依次读人一个关键字为key的结点, 将此结点插人二叉排序树T中
void CreateBST(BSTree& T)
{
InitBiTree(T);
ElemType e = { 0,'\0' };
printf("请输入新结点的关键字key值:");
scanf_s(" %d", &e.Key);
while (e.Key != ENDFLAG) //ENDFLAG为自定义常量-1,作为输入结束标志
{
InsertBST(T, e);
e = { 0,'\0' };
printf("请输入新结点的关键字key值:");
scanf_s(" %d", &e.Key);
}
}
//先序递归遍历二叉排序树
void preOrderTraverse(BSTree T)
{
if (T) //只有当T不为空时才访问它的成员
{
printf(" %d", T->data.Key);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
//中序递归遍历二叉排序树
void InOrderTraverse(BSTree T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf(" %d", T->data.Key);
InOrderTraverse(T->rchild);
}
}
//后序递归遍历二叉排序树
void posOrderTraverse(BSTree T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf(" %d", T->data.Key);
}
}
//输出大于等于x的关键字
void Judge_x(BSTree T, int x)
{
if (T)
{
Judge_x(T->lchild, x);
if (T->data.Key >= x)
{
printf("%d ", T->data.Key);
}
Judge_x(T->rchild, x);
}
}
习题4
已知二叉树T的结点形式为(llink,data, count, rlink), 在树中查找值为X的结点,若找到, 则记数(count)加1; 否则,作为一个新结点插入树中,插入后仍为二叉排序树,写出其非递归算法。
c
#include <stdio.h>
#include <stdlib.h>
#define ENDFLAG -1 //自定义常量,作为输入结束标志
typedef int KeyType;
typedef char InfoType;
//二叉排序树的二叉链表存储表示
typedef struct
{
KeyType Key;
InfoType otherinfo;
}ElemType;
typedef struct BSTNode
{
ElemType data;
int count;
struct BSTNode* lchild;
struct BSTNode* rchild;
}BSTNode, * BSTree;
void InitBiTree(BSTree& T);
void InsertBST(BSTree& T, KeyType e);
void CreateBST(BSTree& T);
void preOrderTraverse(BSTree T);
void InOrderTraverse(BSTree T);
void posOrderTraverse(BSTree T);
void SearchBSTree(BSTree& T, KeyType e);
int main()
{
BSTree T = NULL;
KeyType KEY = 0;
char choice = '\0';
InitBiTree(T);
CreateBST(T);
printf("\n二叉排序树链表的先序序列为: ");
preOrderTraverse(T);
printf("\n二叉排序树链表的中序序列为: ");
InOrderTraverse(T);
printf("\n二叉排序树链表的后序序列为: ");
posOrderTraverse(T);
while (1)
{
printf("\n\n请输入要查找的关键字值:");
scanf_s(" %d", &KEY);
SearchBSTree(T, KEY);
printf("\n二叉排序树链表的先序序列为: ");
preOrderTraverse(T);
printf("\n二叉排序树链表的中序序列为: ");
InOrderTraverse(T);
printf("\n二叉排序树链表的后序序列为: ");
posOrderTraverse(T);
printf("\n是否继续?(y/n)");
scanf_s(" %c", &choice);
if (choice != 'y' && choice != 'Y')
{
break;
}
}
return 0;
}
//初始化二叉排序树
void InitBiTree(BSTree& T)
{
T = NULL;
}
//二叉排序树的插入(非递归)
//二叉排序树T中不存在关键字等于key的数据元素时,插入该值.否则count++
void InsertBST(BSTree& T, KeyType e)
{
BSTree f = NULL;
BSTree q = T;
BSTree S = (BSTree)malloc(sizeof(BSTNode));
S->data.Key = e;
S->count = 0; //每查找成功了次数才加1,新建时次数为0
S->lchild = NULL;
S->rchild = NULL;
if (!T) //T为空树
{
T = S;
return;
}
//因为T可能为空树,所以不能把这种情况放在最前面
if (T->data.Key == e)
{
T->count++;
free(S);
S = NULL;
return;
}
while (q && q->data.Key != e)
{
f = q;
if (q->data.Key > e)
{
q = q->lchild;
}
else //if(q->data.Key < e)
{
q = q->rchild;
}
}
if (q)
{
q->count++;
free(S);
S = NULL;
}
else
{
q = S;
//只知f是q的父节点,但是不清楚q是f的哪个子树
if (f->data.Key > e)
{
f->lchild = S;
}
else
{
f->rchild = S;
}
}
}
//算法7.6 二叉排序树的创建(在插入操作的基础上,且是从空的二叉排序树开始的)
//依次读人一个关键字为key的结点, 将此结点插人二叉排序树T中
void CreateBST(BSTree& T)
{
InitBiTree(T);
KeyType Key = 0;
printf("请输入新结点的关键字key值:");
scanf_s(" %d", &Key);
while (Key != ENDFLAG) //ENDFLAG为自定义常量-1,作为输入结束标志
{
InsertBST(T, Key);
printf("请输入新结点的关键字key值:");
scanf_s(" %d", &Key);
}
}
//先序递归遍历二叉排序树
void preOrderTraverse(BSTree T)
{
if (T) //只有当T不为空时才访问它的成员
{
printf("\n Key = %d, count = %d ", T->data.Key, T->count);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
//中序递归遍历二叉排序树
void InOrderTraverse(BSTree T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("\n Key = %d, count = %d ", T->data.Key, T->count);
InOrderTraverse(T->rchild);
}
}
//后序递归遍历二叉排序树
void posOrderTraverse(BSTree T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("\n Key = %d, count = %d ", T->data.Key, T->count);
}
}
//创建后的查找与插入(非递归)
void SearchBSTree(BSTree& T, KeyType e)
{
if (!T)
{
printf("二叉排序树为空,查找失败。\n");
return;
}
BSTree p = T;
BSTree f = NULL;
if (T->data.Key == e)
{
printf("%d查找成功。\n", e);
T->count++;
return;
}
while (p && p->data.Key != e)
{
f = p;
if (p->data.Key > e)
{
p = p->lchild;
}
else
{
p = p->rchild;
}
}
if (p) //说明找到了p->data.Key = e
{
p->count++;
printf("%d查找成功。\n", e);
}
else
{
BSTree S = (BSTree)malloc(sizeof(BSTNode));
S->data.Key = e;
S->count = 0;
S->lchild = NULL;
S->rchild = NULL;
p = S;
if (e > f->data.Key)
{
f->rchild = S;
}
else
{
f->lchild = S;
}
printf("%d查找失败,已插入。\n", e);
}
}
习题5
假设一棵平衡二叉树的每个结点都标明了平衡因子b, 试设计一个算法,求平衡二叉树的高度。
c
#include <stdio.h>
#include <stdlib.h>
#define ENDFLAG -1 //自定义常量,作为输入结束标志
typedef int KeyType;
typedef char InfoType;
//二叉排序树的二叉链表存储表示
typedef struct
{
KeyType Key;
InfoType otherinfo;
}ElemType;
typedef struct BSTNode
{
ElemType data;
int bf; //平衡因子(Balance Factor),
struct BSTNode* lchild;
struct BSTNode* rchild;
}BSTNode, * BSTree;
void InitBiTree(BSTree& T);
void InsertBST(BSTree& T, KeyType e);
void CreateBST(BSTree& T);
void BF_BSTree(BSTree& T);
void preOrderTraverse(BSTree T);
void InOrderTraverse(BSTree T);
void posOrderTraverse(BSTree T);
int Height(BSTree T);
int Balance_Factor(BSTree T);
int Height_BF(BSTree T);
int main()
{
BSTree T = NULL;
InitBiTree(T);
CreateBST(T);
BF_BSTree(T);
printf("\n二叉排序树链表的先序序列为: ");
preOrderTraverse(T);
printf("\n二叉排序树链表的中序序列为: ");
InOrderTraverse(T);
printf("\n二叉排序树链表的后序序列为: ");
posOrderTraverse(T);
//假设已经平衡
printf("\n\n该平衡二叉树的高度为:%d", Height_BF(T));
return 0;
}
//初始化二叉排序树
void InitBiTree(BSTree& T)
{
T = NULL;
}
//算法 7.5 二叉排序树的插入
//前提:当二叉排序树T中不存在关键字等于e.key的数据元素时, 则插入该元素
void InsertBST(BSTree& T, KeyType e)
{
if (!T)
{
BSTree S = (BSTree)malloc(sizeof(BSTNode));
S->data.Key = e;
S->bf = 0;
S->lchild = NULL;
S->rchild = NULL;
T = S; //把新结点*S链接到已找到的插入位置
}
else if (e < T->data.Key)
{
InsertBST(T->lchild, e);
}
else if (e > T->data.Key)
{
InsertBST(T->rchild, e);
}
else
{
printf("当二叉排序树T中存在关键字等于%d的结点,无法插入。\n", e);
return;
}
}
//算法7.6 二叉排序树的创建(在插入操作的基础上,且是从空的二叉排序树开始的)
//依次读人一个关键字为key的结点, 将此结点插人二叉排序树T中
void CreateBST(BSTree& T)
{
InitBiTree(T);
KeyType Key = 0;
printf("请输入新结点的关键字key值:");
scanf_s(" %d", &Key);
while (Key != ENDFLAG) //ENDFLAG为自定义常量-1,作为输入结束标志
{
InsertBST(T, Key);
printf("请输入新结点的关键字key值:");
scanf_s(" %d", &Key);
}
}
//全部创建完成后,根据中序遍历,求每个结点的平衡因子
void BF_BSTree(BSTree &T)
{
if (T)
{
BF_BSTree(T->lchild);
T->bf = Balance_Factor(T);
BF_BSTree(T->rchild);
}
}
//先序递归遍历二叉排序树
void preOrderTraverse(BSTree T)
{
if (T) //只有当T不为空时才访问它的成员
{
printf("\nKey = %d, bf = %d ", T->data.Key,T->bf);
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
//中序递归遍历二叉排序树
void InOrderTraverse(BSTree T)
{
if (T)
{
InOrderTraverse(T->lchild);
printf("\nKey = %d, bf = %d ", T->data.Key, T->bf);
InOrderTraverse(T->rchild);
}
}
//后序递归遍历二叉排序树
void posOrderTraverse(BSTree T)
{
if (T)
{
posOrderTraverse(T->lchild);
posOrderTraverse(T->rchild);
printf("\nKey = %d, bf = %d ", T->data.Key, T->bf);
}
}
//求高度
int Height(BSTree T)
{
if (!T)
{
return 0;
}
else
{
int m = Height(T->lchild);
int n = Height(T->rchild);
if (m > n)
{
return m + 1;
}
else
{
return n + 1;
}
}
}
//根据高度求平衡因子
int Balance_Factor(BSTree T)
{
int left = Height(T->lchild);
int right = Height(T->rchild);
return left - right;
}
//根据平衡二叉排序树的平衡因子求高度
//平衡二叉树,每个结点的平衡因子绝对值不超过1
int Height_BF(BSTree T)
{
int level = 0;
BSTree p = T;
while (p)
{
level++;
if (p->bf < 0) //p->bf == -1
{
p = p->rchild;
}
else //if(p->bf == 1 || p->bf == 0)
{
p = p->lchild;
}
}
return level;
}
习题6
分别写出在散列表中插入和删除关键字为K的一个记录的算法,设散列函数为H, 解决冲突的方法为链地址法。
c
//除留余数法构造散列函数,"链地址法"处理冲突
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define m 13
#define NULLKEY 0
typedef int KeyType;
typedef char InfoType;
typedef struct KeyNode
{
KeyType Key;
InfoType OtherInfo;
struct KeyNode* next;
}KeyNode;
void CreateHash(KeyNode HT[]);
void Insert(KeyNode HT[], KeyType key);
int SearchHash(KeyNode HT[], KeyType key);
int H(KeyType key);
int maxPrimeNumber(int n);
int checkPrimeNumber(int n);
void Delete(KeyNode HT[], KeyType key);
void printHashTable(KeyNode HT[]);
int main()
{
KeyNode HT[m] = { 0 };
KeyType k1 = 0;
KeyType k2 = 0;
char choice = '\0';
CreateHash(HT);
printHashTable(HT);
while (1)
{
printf("\n\n请输入要插入的数值:");
scanf_s(" %d", &k1);
Insert(HT, k1);
printHashTable(HT);
printf("\n\n请输入要删除的数值:");
scanf_s(" %d", &k2);
Delete(HT, k2);
printHashTable(HT);
printf("\n\n是否继续?(y/Y)");
scanf_s(" %c", &choice);
if (choice != 'y' && choice != 'Y')
{
break;
}
}
return 0;
}
//创建散列表
void CreateHash(KeyNode HT[])
{
int i = 0;
int KEY = 0;
int flag = 0;
for (i = 0; i < m; i++)
{
HT[i].Key = NULLKEY;
HT[i].next = NULL;
}
for (i = 1; i <= m; i++)
{
printf("请输入第%d个关键字(结束时输入-1):", i);
scanf_s(" %d", &KEY); //记录个数可以小于表长度
if (KEY != -1)
{
flag = SearchHash(HT, KEY);
if (flag == -1)
{
Insert(HT, KEY);
}
else
{
printf("该元素已存在,无法插入,请重新输入。\n");
i--;
}
}
else
{
break;
}
}
if (i > m)
{
printf("散列表已满。");
return;
}
}
//散列表的查找
int SearchHash(KeyNode HT[], KeyType key)
{
int H0 = H(key);
KeyNode* p = HT[H0].next;
while (p != NULL)
{
if (p->Key == key)
{
return H0; //找见了
}
p = p->next;
}
return -1; //没找见
}
//散列表的插入(链地址法处理冲突)
void Insert(KeyNode HT[], KeyType key)
{
int H0 = H(key);
KeyNode* p = HT[H0].next;
while (p != NULL)
{
if (p->Key == key)
{
printf("该元素已存在,无法插入。\n");
}
p = p->next;
}
KeyNode* r = (KeyNode*)malloc(sizeof(KeyNode));
r->Key = key;
r->next = HT[H0].next;
HT[H0].next = r;
}
//散列函数
/* 采用除留余数法构造散列函数,选择p为小于表长m的最大质数 */
int H(KeyType key)
{
int p = maxPrimeNumber(m);
return key % p;
}
//确定[0,n]范围内的最大质数
int maxPrimeNumber(int n)
{
int i = 0;
int status = checkPrimeNumber(0);
int max = 0;
for (i = 0; i <= n; i++)
{
status = checkPrimeNumber(i);
if (status)
{
max = i;
}
}
return max;
}
//判断一个数是否是质数
int checkPrimeNumber(int n)
{
int i = 0;
int sq = floor(sqrt(n));
if (n <= 1)
{
return 0;
}
if (n == 2 || n == 3)
{
return 1;
}
//只有6x-1和6x+1的数才有可能是质数(但不一定就是,如n=35,还需要继续判断)
if (n % 6 != 1 && n % 6 != 5) //n=4和n=6时,n%6满足该if条件,返回false,正好符合情况
{
return false;
}
/* 如果 i 是简单类型(int ,char),在使用层面,i+=6 与 i=i+6 做的事是一样的,
都是将 i 的值加了6,但生成的可执行代码不一样,且i+=6 与 i=i+6 运行的效率不同,i+=6 肯定更快。 */
//只判断 该与6的倍数相邻的数n 能否被 其它不超过sq 且 也与6的倍数相邻的数i和i+2 整除
// 同样因为"只有与6的倍数相邻的数才可能是质数",所以用i和i+2来判断(i=5\11\17\23\29\35... i+2=7\13\19\25\31\37...)。
// 定理:如果一个数n不能整除 比它小的任何素数(比n小的全部素数一定都包含在i和i+2中),那么这个数n就是素数。
for (i = 5; i <= sq; i+= 6)
{
if (n % i == 0 || n % (i + 2) == 0)
{
return 0;
}
}
//此处for循环中,仍然找的是整数n的因数,所以仍然可以使用定理:如果一个数m不是质数,那么它必定有一个因子≤√m,另一个≥√m。所以i仍然判断到sq就可以。
//真命题"如果数n存在一个大于√n的整数因数,那么它必定存在一个小于√n的整数因数。"的逆否命题也是真命题。
// 即如果一个数n没有小于√n的整数因数,那么它也一定不会有大于√n的整数因数(除了它自己)。
//n = 5 和 n=7 时,不会进入if判断语句,也不会进入for循环,而是直接返回true,此时也判断正确
return true;
}
void printHashTable(KeyNode HT[])
{
int i = 0;
KeyNode* p = NULL;
printf("\n散列表中的元素为:");
for (i = 0; i < m; i++)
{
if (HT[i].next != NULL)
{
printf("\n在%d个位置处,保存的关键字有:", i+1);
for (p = HT[i].next; p; p = p->next)
{
printf("%d ", p->Key);
}
}
//空槽(链表不为空的)不输出,但是其它的元素还是要输出
//链地址法中,散列表每个位置的HT[i].key成员并不存储任何数据,通常设置为 NULLKEY或者不使用
}
}
//散列表的删除
void Delete(KeyNode HT[],KeyType key)
{
int H0 = H(key);
KeyNode* p = HT[H0].next;
KeyNode* q = NULL;
while (p != NULL)
{
if (p->Key == key)
{
break;
}
q = p;
p = p->next;
}
if (!q)
{
HT[H0].next = p->next;
}
else
{
q->next = p->next;
}
if (!p)
{
printf("%d查找失败,无法删除。\n", key);
}
free(p);
p = NULL;
}