试题1(王道7.2.4节综合练习5):
写出折半查找的递归算法。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 10
#define ElemType int
#define Status int
typedef struct{
int data[MAXSIZE]; //存储空间的基地址
int length; //当前长度
}SqList;
void CreatList(SqList &L){ //建立线性表
L.length = 6;
L.data[0] = 2;
L.data[1] = 3;
L.data[2] = 5;
L.data[3] = 7;
L.data[4] = 9;
L.data[5] = 11;
}
int BinarySearch(SqList L,ElemType x,int low,int high){
int mid = (low + high) / 2;
if(low > high)
return -1;
else if(L.data[mid] == x)
return mid;
else if(L.data[mid] < x)
BinarySearch(L, x, mid + 1, high);
else
BinarySearch(L, x, low, mid - 1);
}
int main(){
SqList L;
CreatList(L);
printf("%d", BinarySearch(L, 7, 0, 5));
}
输出:
3
试题2(王道7.2.4节综合练习6):
线性表中各结点检索概率不等时,可用如下策略提高顺序检索的效率:若找到指定的结点,则将该结点与前驱结点(若存在)交换,使得经常被检索的结点尽量位于表的前端。试设计在顺序结构和链式结构的线性表上实现上述策略的顺序检索算法。
此题可以联系链表练习题的第20题:
【试题再现】试题20:设头指针为L的带有表头结点的非循环双向链表,其每个结点中除有prior(前驱指针),data(数据),next(后继指针)域外,还有一个访问频度域freq。在链表被启用前,其值均初始化为零。每当在连表中进行一次Locate(L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非递增的顺序排列,同时最近访问的结点排在频度相同的结点的前面,以便使频繁访问的结点总是靠近表头。试编写符合上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型。
31.链表练习题(2)(王道2023数据结构2.3.7节16-25题)-CSDN博客https://blog.csdn.net/qq_54708219/article/details/133151369顺序表实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 10
#define ElemType int
#define Status int
typedef struct{
int data[MAXSIZE]; //存储空间的基地址
int length; //当前长度
}SqList;
void CreatList(SqList &L){ //建立线性表
L.length = 6;
L.data[0] = 2;
L.data[1] = 3;
L.data[2] = 5;
L.data[3] = 7;
L.data[4] = 9;
L.data[5] = 11;
}
void PrintList(SqList L){
for (int i = 0; i < L.length;i++){
printf("%d ", L.data[i]);
}
}
int Search(SqList &L,ElemType x){
int t;
for (int i = 0; i < L.length;i++){
if(L.data[i] == x){
t = L.data[i - 1]; //交换
L.data[i - 1] = x;
L.data[i] = t;
return i;
}
}
return -1;
}
int main(){
SqList L;
CreatList(L);
PrintList(L);
printf("\n");
printf("%d\n", Search(L, 7));
PrintList(L);
}
输出:
2 3 5 7 9 11
3
2 3 7 5 9 11
链表实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 10
#define ElemType int
#define Status int
//单链表的数据结构
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
//初始化
int InitList(LinkList &L)
{
L = (LNode *)malloc(sizeof(LNode));
L->next = NULL;
return 1;
}
//输出
void PrintList(LinkList L)
{
printf("当前单链表的所有元素:");
LNode *p;
p = L->next;
while (p != NULL)
{
printf("[%d] ", p->data);
p = p->next;
}
printf("\n");
}
int Create(LinkList &L)
{
int n, e;
LNode *temp = L;//声明一个指针指向头结点,用于遍历链表
printf("请输入要输入元素的个数:");
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
LNode *a = (LNode*)malloc(sizeof(LNode));
printf("请输入第%d元素的值:", (i));
scanf("%d", &e);
a->data = e;
temp->next = a;
a->next = NULL;
temp = temp->next;
}
return 1;
}
int Search(LinkList L,ElemType x){
LinkList p = L;
LinkList q = L;
LinkList r;
int i = 0;
while(p!=NULL){
if(p->data != x){
p = p->next;
i = i + 1;
}
else{
if(i > 1){
for (int j = 1; j <= i - 2; j++){
q = q->next;
} //q指向第i-2个元素
r = q->next; //r指向第i-1个元素
q->next = p;
q = p->next; //q指向第i+1个元素
p->next = r;
r->next = q;
}
return i;
}
}
return -1;
}
int main(){
LinkList L;
InitList(L);
Create(L);
PrintList(L);
printf("元素在链表第%d个位置\n", Search(L, 7));
PrintList(L);
}
输出:
请输入要输入元素的个数:6
请输入第1元素的值:2
请输入第2元素的值:3
请输入第3元素的值:5
请输入第4元素的值:7
请输入第5元素的值:9
请输入第6元素的值:11
当前单链表的所有元素:[2] [3] [5] [7] [9] [11]
元素在链表第4个位置
当前单链表的所有元素:[2] [3] [7] [5] [9] [11]
试题3(王道7.3.4节综合练习6):
设计算法,判断给定的二叉树是否是二叉排序树。
看其中序遍历序列是否是递增有序的即可:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 10
#define ElemType int
//二叉排序树的结构体定义
typedef struct BiTNode{
ElemType data; //数据域
BiTNode *lchild; //指向左子树根节点的指针
BiTNode *rchild; //指向右子树根节点的指针
}BiTNode, *BiTree;
int BST_Insert(BiTree &T,ElemType k){ //构造一棵二叉排序树
if(T==NULL){
T = (BiTree)malloc(sizeof(BiTNode));
T->data = k;
T->lchild = NULL;
T->rchild = NULL;
return 1;
}
else if(k==T->data){
return 0;
}
else if(k<T->data){
return BST_Insert(T->lchild, k);
}
else{
return BST_Insert(T->rchild, k);
}
}
int if_BST(BiTree T){
int a[10];
int i = 0;
if (T!=NULL){
if_BST(T->lchild);
a[i] = T->data;
i = i + 1;
if_BST(T->rchild);
}
for (int j = 1; j <= i-1;j++){ //实际上a数组中元素是0到i-1
if(a[j-1] >= a[j]){
return 0;
}
}
return 1;
}
int main(){
BiTree T=NULL;
int a[5] = {4, 2, 1, 3, 5}; //以王道第10题做验证
for (int i = 0; i <= 4;i++){
BST_Insert(T, a[i]);
}
printf("%d",if_BST(T));
return 0;
}
输出:
1
试题4(王道7.3.4节综合练习7):
设计算法求指定结点在给定二叉排序树的层次。
老问题了,直接上递归:
int levelofNode(BiTree T, ElemType x,int level){
if(T==NULL)
return -1;
else{
if(T->data==x)
return level;
else{
if(T->data<x)
return levelofNode(T->rchild, x, level + 1);
else
return levelofNode(T->lchild, x, level + 1);
}
}
}
int main(){
BiTree T=NULL;
int a[5] = {4, 2, 1, 3, 5}; //以王道第10题做验证
for (int i = 0; i <= 4;i++){
BST_Insert(T, a[i]);
}
printf("%d",levelofNode(T,3,1));
return 0;
}
输出:
3
试题5(王道7.3.4节综合练习8):
利用二叉树的遍历思想编写一个判断二叉树是否是平衡二叉树的算法。
这里利用层次遍历每一个结点,检查平衡因子绝对值是否小于1。全部通过才返回True。
int Depth(BiTree T){
if(T==NULL)
return 0;
else{
return (Depth(T->lchild) >= Depth(T->rchild)) ? Depth(T->lchild) + 1 : Depth(T->rchild) + 1;
}
}
int abs(int x){
return x >= 0 ? x : -x;
}
bool ifBalanceTree(BiTree T){ //层次遍历每一个结点
int balance = 0;
Queue q;
InitQueue(q);
BiTree p = T;
InsertQueue(q, p);
while(!IsQueueEmpty(q)){
p = DeleteQueue(q, p);
balance = abs(Depth(p->lchild) - Depth(p->rchild));
if(balance > 1)
return false;
if(p->lchild!=NULL)
InsertQueue(q, p->lchild);
if(p->rchild!=NULL)
InsertQueue(q, p->rchild);
}
return true;
}
int main(){
BiTree T=NULL;
int a[5] = {1, 2, 3, 4, 5}; //以王道第10题做验证
for (int i = 0; i <= 4;i++){
BST_Insert(T, a[i]);
}
printf("%d",ifBalanceTree(T));
return 0;
}
输出:
1 //int a[5] = {4, 2, 1, 3, 5};
0 //int a[5] = {1, 2, 3, 4, 5};
试题6(王道7.3.4节综合练习9):
设计算法求给定二叉排序树最小和最大的关键字。
最小关键字在最左下,最大关键字在最右下,抓住这一点判断即可。此题不需要从头遍历把所有结点全部输出。
int maxvalue(BiTree T){ //求最大关键字
BiTree p=T;
while (p->rchild!=NULL){
p = p->rchild;
}
return p->data;
}
int main(){
BiTree T=NULL;
int a[5] = {4, 2, 1, 3, 5}; //以王道第10题做验证
for (int i = 0; i <= 4;i++){
BST_Insert(T, a[i]);
}
printf("%d",maxvalue(T));
return 0;
}
int minvalue(BiTree T){ //求最小关键字
BiTree p=T;
while (p->lchild!=NULL){
p = p->lchild;
}
return p->data;
}
int main(){
BiTree T=NULL;
int a[5] = {4, 2, 1, 3, 5}; //以王道第10题做验证
for (int i = 0; i <= 4;i++){
BST_Insert(T, a[i]);
}
printf("%d",minvalue(T));
return 0;
}
试题7(王道7.3.4节综合练习10):
设计一个算法,从大到小输出二叉排序树中所有值不小于k的关键字。
倒序访问:显然先访问右子树,然后根结点,最后左子树,然后检查并输出。
void printoverk(BiTree T,int k){ //求最小关键字
if(T!=NULL){
printoverk(T->rchild, k);
if(T->data>k){
printf("%d ", T->data);
}
printoverk(T->lchild, k);
}
}
int main(){
BiTree T=NULL;
int a[5] = {4, 2, 1, 3, 5}; //以王道第10题做验证
for (int i = 0; i <= 4;i++){
BST_Insert(T, a[i]);
}
printoverk(T, 2);
return 0;
}
输出:
5 4 3
试题8(王道7.3.4节综合练习11):
编写一个递归算法,在一棵具有n个结点的二叉排序树上查找第k小的元素,并返回该结点的指针。要求算法的平均时间复杂度是,二叉排序树每个结点中除了data,lchild,rchild外,增设一个count成员,保存以该结点为根的子树的结点个数。
函数的参数有两个:二叉树指针T和查找第k个最小元素。
//求树的结点数(递归)
int Number_Node(BiTree T){
if(T==NULL)
return 0;
else{
return Number_Node(T->lchild) + Number_Node(T->rchild) + 1;
}
}
int BST_Insert(BiTree &T,ElemType k){ //构造一棵二叉排序树
if(T==NULL){
T = (BiTree)malloc(sizeof(BiTNode));
T->data = k;
T->lchild = NULL;
T->rchild = NULL;
return 1;
}
else if(k==T->data){
return 0;
}
else if(k<T->data){
return BST_Insert(T->lchild, k);
}
else{
return BST_Insert(T->rchild, k);
}
}
void BST_Insertcount(BiTree &T){ //修改count的数值
Queue q;
InitQueue(q);
BiTree p = T;
InsertQueue(q, p);
while(!IsQueueEmpty(q)){
p = DeleteQueue(q, p);
p->count = Number_Node(p);
if(p->lchild!=NULL)
InsertQueue(q, p->lchild);
if(p->rchild!=NULL)
InsertQueue(q, p->rchild);
}
}
BiTree SearchSmallk(BiTree T,int k){ //寻找第k小的元素
if(k<1||k>T->count) //k不合法,直接返回空
return NULL;
if(T->lchild == NULL){
if(k == 1)
return T;
else
return SearchSmallk(T->rchild, k - 1); //第k小的元素必在右子树
}
else{
if(T->lchild->count == k-1)
return T;
else if(T->lchild->count < k-1)
return SearchSmallk(T->rchild, k - T->lchild->count - 1); //第k小的元素必在右子树
else
return SearchSmallk(T->lchild, k); //第k小的元素必在左子树
}
}
int main(){
BiTree T=NULL;
BiTree p;
int a[5] = {4, 2, 1, 3, 5}; //以王道第10题做验证
for (int i = 0; i <= 4;i++){
BST_Insert(T, a[i]);
}
BST_Insertcount(T);
p = SearchSmallk(T, 3);
printf("%d", p->data);
return 0;
}
输出:
3