《数据结构与测绘程序设计》试题详细解析(仅供参考)

news2024/11/24 17:25:48

一. 选择题(每空2分,本题共30分)

(1)在一个单链表中,已知q所指结点是p所指结点的前驱结点,若在q和p之间插入结点s,则执行(  B  )。

A. s->next=p->next; p->next=s;                                      C. p->next=s->next; s->next=p;

B. q->next=s; s->next=p;                                                D. p->next=s; s->next=q;

【解析】:

在单链表中插入结点s,需要调整相关结点的指针指向。根据题目中给出的信息,q所指结点是p所指结点的前驱结点,因此需要先将q的next指针指向s,即q->next=s,然后将s的next指针指向p,即s->next=p。这样就完成了结点s的插入操作,同时保持了链表的正确连接关系。所以选项B是正确的语句。

(2)对于一个头指针为head的带头结点的单链表,判定该表为空表的条件是(  B  );对于不带头结点的单链表,判定空表的条件为(  A  )。
A. head= =NULL       B. head->next= =NULL       C. head->next= =head       D. head!=NULL

【解析】:

对于一个带头结点的单链表,判定该表为空表的条件是头结点的 next 指针为空,即 head->next == NULL。对于一个不带头结点的单链表,判定空表的条件是单链表的头指针为空,即 head == NULL。因为在不带头结点的单链表中,头指针指向第一个元素,如果头指针为空,则说明链表中没有任何元素。

(3)向一个栈顶指针为top的链栈中插入一个x结点,则执行(  B  )。
A. top->next=x                                                              C. x->next=top->next; top->next=x
B. x->next=top; top=x                                                   D. x->next=top, top=top->next

【解析】:

链栈是一种特殊的链表结构,插入结点时需要更新栈顶指针。在向链栈中插入结点x时,需要将x插入到栈顶位置,并更新栈顶指针top。

选项B中的语句x->next=top表示将结点x的next指针指向当前的栈顶元素,即将x插入到栈顶位置。同时,top=x将栈顶指针top更新为新插入的结点x。这样就完成了结点x的插入操作,并且正确地更新了栈顶指针。

所以选项B是正确的语句。

(4)链栈执行Pop操作,并将出栈的元素存在x中,应该执行(  D  )。

A. x=top; top=top->next                                                   C. x=top->data

B. top=top->next; x=top->data                                         D. x=top->data; top=top->next

【解析】:

在链栈执行Pop操作时,需要将栈顶元素出栈,并将其数据域保存到x中。然后,更新栈顶指针top,使其指向下一个元素,完成出栈操作。

选项D中的语句x=top->data表示将栈顶元素的数据域保存到x中,而top=top->next表示将栈顶指针top更新为下一个元素的地址,即完成出栈操作。

所以选项D是正确的语句。

(5)设有一个顺序共享栈Share[0:n-1],其中第一个栈顶指针top1的初值为-1,第二个栈顶指针top2的初值为n,则判断共享栈满的条件是(   )。
A. top2-top1= =1          B. topl-top2= =1          C. top1= =top2          D.以上都不对

【解析】:

共享栈满的条件是两个栈顶指针之间相隔一个元素,因此,当两个栈满时,它们的栈顶指针相邻,即top2 - top1 == 1。

(6)用链式存储方式的队列进行删除操作时需要(  D  )。

 A. 仅修改头指针     B. 头尾指针都要修改     C. 仅修改尾指针     D. 头尾指针可能都要修改

【解析】:

在链式存储方式的队列中,删除操作是从队列头部删除元素。如果删除的是队列中唯一的元素(即队列只有一个节点),那么删除后队列为空,需要同时修改头指针和尾指针,使它们都指向空。

另外,在某些特殊情况下,头指针和尾指针可能都需要被修改。例如,在循环队列中,当删除的是队列的最后一个元素时,需要将头指针和尾指针都指向空。

所以选项D. 头尾指针可能都要修改 是正确的。

(7)在一个链队列中,假设队头指针为front,队尾指针为rear,x所指向的元素需要入队,则需要执行的操作为(  D  )。
A. front=x, front=front->next                                    C. x->next=front->next, front=x
B. rear->next=x, rear=x                                           D. rear->next=x, x->next=null, rear=x

【解析】:

在链式存储方式的队列中,入队操作是在队列尾部插入元素。因此,需要修改队尾指针rear的指向,使其指向新插入的节点x,同时修改该节点的指针域next,使其指向空。

所以选项D. rear->next=x, x->next=null, rear=x 是正确的。而其他选项中,选项A中仅修改了front的指向,选项B中仅修改了rear的指向,选项C中修改了front和x的指向,这些都是不正确的。

(8)若一棵二叉树有126个结点,在第7层(根结点在第1层)至多有(  B  )个结点。

A. 32                         B. 63                         C. 64                         D.不存在第7层

【解析】:

由于根结点在第 1 层,所以在第 7 层至多有 2^(7−1)−1=63 个结点。即,在第 7 层最多只有 63 个结点。

(9)已知一棵二叉树的后序序列为DABEC,中序序列为DEBAC ,则先序序列为(  D  )。

A. ACBED                    B. DEABC                    C. DECAB                    D. CEDBA

【解析】:

  1. 后序序列的最后一个元素一定是根节点,即 C 是根节点。
  2. 在中序序列中找到根节点 C,根据根节点将中序序列划分为左子树和右子树。根据中序序列,可以得到左子树序列为 DEBA,右子树序列为空。
  3. 根据左子树序列 DEBA,结合后序序列,可以得到左子树的根结点为 E。
  4. 重复上述步骤,对左子树和右子树进行递归分析即可得到该二叉树的结构图。

(10)一个栈的入栈序列为 1,2,3,…,n,出栈序列是P1,P2,P3,…,Pn。若P2=3 ,则P3 可能取值的个数是(  C  )。
A. n-3                         B. n-2                         C. n-1                         D.无法确定

【解析】:

根据题目描述,入栈序列为 1,2,3,…,n,出栈序列为 P1,P2,P3,…,Pn。如果 P2=3,则 P3 可能取值的个数可以通过观察入栈和出栈的过程来确定。

在这个例子中,元素 1 入栈后,P1 不会立即出栈,因为 P2=3,所以元素 3 入栈后,P3 才会出栈。也就是说,对于元素 3 来说,在它入栈之前,至少有两个元素(1 和 2)在它上面,所以 P3 可能的取值个数为 n-1。

因此,答案是 C. n-1。

(11)链式栈结点为 (data, link),top 指向栈顶,若想摘除栈顶结点,并将删除结点的值保存到x中,则应执行操作(  A  )。
A. x=top->data; top=top->link;                                   C. top=top->link; x=top->link;

B. x=top; top=top->link;                                              D. x=top->link;

【解析】:

在链式栈中,栈顶指针top指向栈顶结点。如果要摘除栈顶结点并将删除结点的值保存到x中,需要先保存栈顶结点的值,然后修改栈顶指针top,使其指向下一个结点。

所以选项A. x=top->data; top=top->link; 是正确的。它首先将栈顶结点的值保存到x中,然后将栈顶指针top移动到下一个结点。

其他选项中,选项B中将x直接指向top,而不是保存栈顶结点的值,选项C中修改top后再将x指向top的link域,选项D中将x指向top的link域,这些都是不正确的。

(12)设栈 S 和队列 Q 的初始状态为空,元素 e1、e2、e3、e4、e5 和 e6 依次进入栈 S,一个元素出栈后即进入 Q,若 6 个元素出队的序列是 e2、e4、e3、e6、e5 和 e1,则栈 S 的容量至少应该是(   )。
A. 2                              B. 3                              C. 4                              D. 6

【解析】:

根据题目描述,元素依次进入栈 S,然后一个元素出栈后即进入队列 Q。那么来模拟一下这个过程:

  1. e1 进入栈 S
  2. e2 进入栈 S
  3. e3 进入栈 S
  4. e4 进入栈 S

此时栈 S 中的元素为 e1、e2、e3、e4,栈的容量至少应该是 4。

  1. e4 出栈并进入队列 Q
  2. e3 出栈并进入队列 Q
  3. e2 出栈并进入队列 Q

此时栈 S 中的元素为 e1,栈的容量可以为 1。

  1. e5 进入栈 S
  2. e6 进入栈 S

此时栈 S 中的元素为 e1、e5、e6,栈的容量至少应该是 3。

因此,根据题目给出的出队序列,栈 S 的容量至少应该是 3,所以答案是 B. 3。

(13)若一个栈以向量 V[1,…,n] 存储,初始栈顶指针 top 设为 n+1,则元素x进栈的正确操作是(  C  )。
A. top++; V[top]=x;        B. V[top]=x; top++;        C. top--; V[top]=x;        D. V[top]=x; top--;

【解析】:

根据题目描述,栈以向量 V[1,…,n] 存储,并且初始栈顶指针 top 设为 n+1。这意味着栈的存储空间是从下标 1 到 n 的连续向量,初始时栈为空,栈顶指针指向 n+1。

当元素 x 进栈时,需要先将栈顶指针 top 向下移动一位,然后将元素 x 存储到栈顶位置 V[top]。所以选项 C. top--; V[top]=x; 是正确的。

其他选项中,选项 A 中先将栈顶指针 top 向上移动一位,然后再将元素 x 存储到栈顶位置 V[top],这样会导致栈顶指针指向错误的位置;选项 B 中先将元素 x 存储到栈顶位置 V[top],然后再将栈顶指针 top 向上移动一位,这样会导致元素 x 存储在了错误的位置;选项 D 中先将元素 x 存储到栈顶位置 V[top],然后再将栈顶指针 top 向下移动一位,这样会导致栈顶指针指向错误的位置。

因此,正确的语句是 C. top--; V[top]=x;

(14)设有一个 10 阶的对称矩阵 A,采用压缩存储方式,以行序为主存储,a11 为第一元素,其存储地址为 1,每个元素占一个地址空问,则 a85 的地址为(  C  )。

A. 13                                  B. 32                                   C. 33                                   D. 40

【解析】:

根据题目描述,对称矩阵 A 采用压缩存储方式,以行序为主存储。矩阵 A 是 10 阶的,即有 10 行和 10 列。

在压缩存储方式中,只需要存储矩阵的上三角或下三角部分(不包括对角线),因为对称矩阵的上下三角是对称的。

根据这种压缩存储方式,矩阵 A 的第一行(从 a11 到 a1n)的元素将依次存储在地址 1 到 n-1 的位置上。第二行(从 a22 到 a2n)的元素将依次存储在地址 n 到 2n-3 的位置上。

依此类推,矩阵 A 的第十行(从 a101 到 a10n)的元素将依次存储在地址 9n-8 到 9n-9 的位置上。

所以,a85 的地址为 33 是正确的。

二. 算法设计题(每小题5分,本题共20分)

(1)已知某二叉树的先序序列和中序序列分别为ABDEHCFIMGJKL和DBHEAIMFCGKLJ,请画出这棵二叉树,并画出二叉树对应的森林。

【标答】:

【解析】:

首先,根据先序序列和中序序列构造二叉树的步骤如下:

  1. 先序序列的第一个节点为整棵树的根节点,这里根据先序序列可以确定根节点为 A。
  2. 在中序序列中找到根节点所在位置,根节点将中序序列分为左子树和右子树的中序序列。可以确定左子树为 DBHE, 右子树为 IMFCGKLJ。
  3. 根据左子树可以确定左子树的根节点为 B, 根据右子树可以确定右子树的根节点为 C。
  4. 重复以上步骤,对左子树和右子树分别进行递归,直到得到整棵树的结构。

根据上述步骤,可以得到以上二叉树的结构。

(2)回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法(伪码)判定给定的字符序列是否为回文。(提示:将一半字符入栈。)

【标答】:

 【解析】:

以下是一个“用于判断给定的字符序列是否为回文”的C语言代码:

#include <stdio.h>
#include <string.h>

#define MAX_SIZE 100

// 定义栈结构
struct Stack {
    int top;
    char items[MAX_SIZE];
};

// 初始化栈
void initialize(struct Stack *s) {
    s->top = -1;
}

// 将元素压入栈
void push(struct Stack *s, char c) {
    s->items[++(s->top)] = c;
}

// 从栈中弹出元素
char pop(struct Stack *s) {
    return s->items[(s->top)--];
}

// 判断字符序列是否为回文
int isPalindrome(char *str) {
    int length = strlen(str);
    int i, mid = length / 2;
    struct Stack s;

    // 初始化栈
    initialize(&s);

    // 将前一半字符入栈
    for (i = 0; i < mid; i++) {
        push(&s, str[i]);
    }

    // 比较栈中的字符与字符串的后一半字符
    for (i = mid + length % 2; i < length; i++) {
        if (str[i] != pop(&s)) {
            return 0;
        }
    }

    return 1;
}

int main() {
    char str[MAX_SIZE];
    printf("请输入一个字符序列:");
    scanf("%s", str);

    if (isPalindrome(str)) {
        printf("是回文。\n");
    } else {
        printf("不是回文。\n");
    }

    return 0;
}

在上述代码中,首先定义了一个栈的结构和相关操作函数,并且使用这些操作函数来实现判断回文的功能。主要步骤包括:

  1. 初始化栈并定义栈操作函数。
  2. 将给定字符序列的前一半字符依次入栈。
  3. 依次比较栈中的字符与字符序列的后一半字符,如果全部相同则判定为回文。

这个算法的时间复杂度为 O(n),其中 n 是字符序列的长度。

(3)设L为带头结点的单链表,编写算法(伪码)实现从尾到头反向输出每个结点的值。

【标答】:

【解析】:

以下是实现“从尾到头反向输出每个结点的值”的C语言代码:

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int val;
    struct ListNode* next;
};

void printListReverse(struct ListNode* head) {
    if (head == NULL) {
        return;
    }
    printListReverse(head->next);
    printf("%d ", head->val);
}

int main() {
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* current = head;

    // 创建带有20个节点的链表
    for (int i = 1; i <= 20; i++) {
        struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
        newNode->val = i;
        newNode->next = NULL;
        current->next = newNode;
        current = newNode;
    }

    printListReverse(head->next);

    current = head;
    struct ListNode* temp;
    while (current != NULL) {
        temp = current;
        current = current->next;
        free(temp);
    }

    return 0;
}

这个算法使用递归来实现从尾到头反向输出每个结点的值。首先定义了一个printListReverse函数,它接收链表的头结点指针作为参数。

在函数中,首先判断头结点是否为空,如果为空则直接返回。如果头结点不为空,那么先递归调用printListReverse函数,传入头结点的下一个结点作为参数,实现从尾到头的输出。然后再输出当前头结点的值。

main函数中,创建了一个带头结点的单链表,并调用printListReverse函数来反向输出每个结点的值。

最后,为了防止内存泄漏,在程序的末尾释放了动态分配的内存。

(4)已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法(伪码)求出两个集合A和B 的差集(即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。

 【解析】:

以下是实现“求两个递增排列链表A和B的差集,并返回差集元素个数”的C语言代码:

#include <stdio.h>
#include <stdlib.h>

// 定义链表节点结构
struct ListNode {
    int val;
    struct ListNode *next;
};

// 求两个递增排列链表的差集
int difference(struct ListNode *A, struct ListNode *B) {
    struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
    head->next = NULL;
    struct ListNode *current = head;

    while (A != NULL && B != NULL) {
        if (A->val < B->val) {
            struct ListNode *newNode = (struct ListNode *)malloc(sizeof(struct ListNode));
            newNode->val = A->val;
            newNode->next = NULL;
            current->next = newNode;
            current = newNode;
            A = A->next;
        } else if (A->val > B->val) {
            B = B->next;
        } else {
            A = A->next;
            B = B->next;
        }
    }

    while (A != NULL) {
        struct ListNode *newNode = (struct ListNode *)malloc(sizeof(struct ListNode));
        newNode->val = A->val;
        newNode->next = NULL;
        current->next = newNode;
        current = newNode;
        A = A->next;
    }

    int count = 0;
    current = head->next;
    while (current != NULL) {
        count++;
        current = current->next;
    }

    // 释放内存
    struct ListNode *temp;
    current = head->next;
    while (current != NULL) {
        temp = current;
        current = current->next;
        free(temp);
    }
    free(head);

    return count;
}

int main() {
    // 构建两个递增排列的链表A和B用于测试
    struct ListNode *A = (struct ListNode *)malloc(sizeof(struct ListNode));
    A->next = NULL;

    struct ListNode *B = (struct ListNode *)malloc(sizeof(struct ListNode));
    B->next = NULL;

    // 在链表A中添加元素
    struct ListNode *currentA = A;
    for (int i = 1; i <= 5; i++) {
        struct ListNode *newNode = (struct ListNode *)malloc(sizeof(struct ListNode));
        newNode->val = i * 2;
        newNode->next = NULL;
        currentA->next = newNode;
        currentA = newNode;
    }

    // 在链表B中添加元素
    struct ListNode *currentB = B;
    for (int i = 1; i <= 5; i++) {
        struct ListNode *newNode = (struct ListNode *)malloc(sizeof(struct ListNode));
        newNode->val = i * 3;
        newNode->next = NULL;
        currentB->next = newNode;
        currentB = newNode;
    }

    // 求链表A和B的差集,并返回差集元素个数
    int count = difference(A->next, B->next);

    // 输出差集元素个数
    printf("差集元素个数: %d\n", count);

    // 释放内存
    struct ListNode *temp;
    currentA = A;
    while (currentA != NULL) {
        temp = currentA;
        currentA = currentA->next;
        free(temp);
    }
    currentB = B;
    while (currentB != NULL) {
        temp = currentB;
        currentB = currentB->next;
        free(temp);
    }

    return 0;
}

上述代码是用C语言实现的一个求两个递增排列链表A和B的差集,并返回差集元素个数的程序。

代码首先定义了链表节点结构struct ListNode,包含一个整数值val和指向下一个节点的指针next

接下来定义了求差集的函数difference,该函数接收两个参数:链表A的头节点指针和链表B的头节点指针。

在函数内部,创建了一个新的头节点head,并将其指针赋给变量current,用于构建存储差集的新链表。

接下来使用while循环遍历链表A和B的元素,直到其中一个链表为空。在循环中,根据当前节点的值的大小关系,判断是否将该节点加入到新链表中。如果节点的值小于B链表的当前节点值,则将该节点加入到新链表中,并更新current指针和A指针;如果节点的值大于B链表的当前节点值,则说明该节点不在差集中,将B指针向后移动;如果节点的值等于B链表的当前节点值,则说明该节点既在A链表中又在B链表中,将A和B指针都向后移动。

当其中一个链表遍历完后,再将剩余的节点加入到新链表中。

接下来使用循环统计新链表的节点个数,并将其返回。

在main函数中,构建了两个递增排列的链表A和B,并调用difference函数求差集,并将差集元素个数存储在变量count中。

最后输出差集元素个数。

为了防止内存泄漏,在程序的末尾释放了动态分配的内存。

这段代码主要通过遍历链表A和B的方法,找出只在A链表中出现的节点,构建一个新的链表来存储差集,并返回差集元素个数。

三. 编程题(本题共20分)

阅读以下C#代码,将序号所指的方框内代码进行解释说明。

【标答】:

 

四. 工程案例分析题(本题共30分)

选取一个测绘程序设计与开发案例,详细阐述面向对象设计方法的优势,并详细分析该程序所包含的类的构建、对象、属性、方法及构造函数设计与实现的步骤和流程图。

根据自行选定的测量程序题目,介绍程序需要实现的功能,使用面向对象的设计方法,分析程序所需的对象、类、属性、方法、及继承关系等,列出该程序的功能结构图,展示类和对象之间的层次关系。(15分)

开发实施流程:①系统分析②系统设计③系统详细设计④编码实施,详细介绍各阶段的操作步骤和结果。(15分)

【解析】:

下面是一个关于“四等水准测量”测绘程序设计与开发的案例:

一、程序功能介绍: 该测绘程序旨在通过实施四等水准测量来确定地面高程。程序的主要功能包括:

  1. 数据输入:用户可以输入测量数据,包括观测点的坐标和测量结果。

  2. 数据处理:根据输入的观测数据,程序将计算出各观测点的高程值。

  3. 数据输出:程序将输出计算得到的观测点的高程值,并可以生成高程图或其他相关报告。

二、面向对象设计方法的优势: 面向对象设计方法可以将整个测绘程序划分为多个对象,每个对象负责完成特定的任务。这种设计方法的优势在于:

  1. 模块化:通过将系统划分为独立的对象,可以实现模块化开发和维护。每个对象只关注自己的功能,降低了代码的复杂性。

  2. 可扩展性:通过定义类和对象之间的继承关系,可以轻松地扩展系统功能。例如,可以通过创建新的子类来支持不同类型的水准测量。

  3. 代码重用:通过使用继承和多态的概念,可以将通用的功能封装在基类中,并在子类中重写或扩展特定的功能。这样可以提高代码的重用性和可维护性。

  4. 系统灵活性:面向对象设计方法允许对象之间的松耦合关系,当需求变化时,可以更容易地修改或替换特定的对象,而不会影响到整个系统的其他部分。

三、类的构建、对象、属性和方法设计: 在“四等水准测量”测绘程序中,可以考虑以下类的构建、对象、属性和方法设计:

  1. 类:Point(点)

    • 属性:高程
    • 方法:获取坐标、设置高程
  2. 类:Observation(观测)

    • 属性:观测结果
    • 方法:添加观测结果、计算高程差
  3. 类:Survey(测量)

    • 属性:观测点集合
    • 方法:添加观测、计算高程、生成报告

四、功能结构图和类层次关系: 以下是一个简化的功能结构图,展示了类和对象之间的层次关系:

              +-------+
              | Point |
              +-------+
                 |    \
                 |     \ (has-a)
                 |      \
            +---------+   +--------------+
            |         |   | Observation  |
            | Survey  |   +--------------+
            |         |   | - StartPoint |
            +---------+   | - EndPoint   |
                           | - Result     |
                           +--------------+

在此类层次结构中,Survey 包含多个 Observation,每个 Observation 包含两个 Point(StartPoint 和 EndPoint)以及测量结果。 Survey 类负责管理观测点集合,并通过调用 Observation 的方法来计算高程。

五、开发实施流程:

  1. 系统分析:

    • 确定需求:明确系统需要支持的功能和用户需求。
    • 分析数据结构:确定需要的数据类型和数据结构,如 Point、Observation 和 Survey。
    • 划分模块:将系统划分为独立的模块和类。
  2. 系统设计:

    • 定义类和对象:根据分析结果,定义类和对象,并确定它们之间的关系。
    • 设计属性和方法:为每个类定义合适的属性和方法,以支持程序的功能。
  3. 系统详细设计:

    • 编写类的详细设计文档:描述每个类的属性、方法和关系,包括输入输出参数、函数调用关系等。
    • 绘制类图:使用UML或其他工具,绘制类之间的关系图和继承关系。
  4. 编码实施:

    • 根据系统详细设计文档,逐个实现每个类和对象。
    • 进行单元测试:测试每个类的功能是否正常运行,确保代码质量和功能正确性。
    • 进行集成测试:将各个模块整合到一个完整的系统中,并进行系统级别的测试。

以上是基于面向对象设计方法的测绘程序设计与开发案例的一般步骤和思路。具体的实现细节和流程可能因具体需求和编程语言而有所不同。在实际开发中,还需要考虑异常处理、数据存储和用户界面等方面的设计和实现。

【关于BF算法(Brute Force Algorithm)】:

BF算法(Brute Force Algorithm)是一种简单直观的字符串匹配算法,也称为暴力匹配算法。它的基本思想是通过对主串和模式串逐个字符进行比较,以找到匹配的子串。虽然BF算法的时间复杂度较高,但在一些简单的应用场景中仍然具有一定的实用价值。

下面是C语言实现的BF算法代码:

#include <stdio.h>
#include <string.h>

int BF(char *text, char *pattern) {
    int i = 0, j = 0;
    int text_len = strlen(text);
    int pattern_len = strlen(pattern);

    while (i < text_len && j < pattern_len) {
        if (text[i] == pattern[j]) {
            i++;
            j++;
        } else {
            i = i - j + 1;  // 主串回溯到上次匹配的下一个位置
            j = 0;  // 模式串回溯到开头
        }
    }

    if (j == pattern_len) {
        return i - j;  // 返回匹配的子串在主串中的起始位置
    } else {
        return -1;  // 未找到匹配的子串
    }
}

int main() {
    char text[] = "hello, world!";
    char pattern[] = "world";
    int index = BF(text, pattern);
    if (index != -1) {
        printf("Pattern found at index: %d\n", index);
    } else {
        printf("Pattern not found\n");
    }
    return 0;
}

在上面的代码中,BF函数用于实现BF算法的字符串匹配过程。主要思路是通过两个循环对主串和模式串进行逐个字符的比较,并在不匹配时进行回溯。最后的main函数演示了如何使用BF函数进行字符串匹配。

需要注意的是,BF算法的时间复杂度为O(m*n),其中m为主串长度,n为模式串长度。在实际应用中,对于较长的字符串,BF算法可能效率较低,可以考虑其他更高效的字符串匹配算法,如KMP算法、Boyer-Moore算法等。

【关于图在C语言中的矩阵存储算法和单链表存储算法】:

图的矩阵存储算法(邻接矩阵):

邻接矩阵是一种常见的图的表示方法,使用一个二维数组来表示图中各顶点之间的关系。该二维数组的行和列分别对应图中的顶点,数组元素的值表示对应顶点之间是否存在边或弧。

下面是在C语言中实现图的邻接矩阵存储算法的代码:

#include <stdio.h>

#define MAX_VERTICES 100

typedef struct {
    int matrix[MAX_VERTICES][MAX_VERTICES];
    int numVertices;
} Graph;

void initializeGraph(Graph *graph, int numVertices) {
    graph->numVertices = numVertices;
    for (int i = 0; i < numVertices; i++) {
        for (int j = 0; j < numVertices; j++) {
            graph->matrix[i][j] = 0; // 初始化矩阵元素为0,表示没有边
        }
    }
}

void addEdge(Graph *graph, int startVertex, int endVertex) {
    graph->matrix[startVertex][endVertex] = 1; // 添加边,将对应位置置为1
    // 如果是有向图,只需上述一行代码
    // 如果是无向图,还需添加下面一行代码
    graph->matrix[endVertex][startVertex] = 1; 
}

void printGraph(Graph *graph) {
    printf("Adjacency Matrix:\n");
    for (int i = 0; i < graph->numVertices; i++) {
        for (int j = 0; j < graph->numVertices; j++) {
            printf("%d ", graph->matrix[i][j]);
        }
        printf("\n");
    }
}

int main() {
    Graph graph;
    int numVertices = 5;
    initializeGraph(&graph, numVertices);

    addEdge(&graph, 0, 1);
    addEdge(&graph, 1, 2);
    addEdge(&graph, 2, 3);
    addEdge(&graph, 3, 4);
    addEdge(&graph, 4, 0);

    printGraph(&graph);

    return 0;
}

在上述代码中,首先定义了一个Graph结构体,其中的matrix数组就是邻接矩阵。initializeGraph函数用于初始化图,将所有矩阵元素都置为0。addEdge函数用于添加边,将对应位置的矩阵元素置为1。printGraph函数用于打印邻接矩阵。

图的单链表存储算法(邻接表):

邻接表是另一种常见的图的表示方法,使用一个数组和链表结构来表示图中各顶点之间的关系。数组的每个元素对应一个顶点,而每个元素中的链表存储该顶点的邻接顶点。

下面是在C语言中实现图的邻接表存储算法的代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int vertex;
    struct Node *next;
} Node;

typedef struct {
    Node *head;
} AdjList;

typedef struct {
    int numVertices;
    AdjList *array;
} Graph;

Node *createNode(int vertex) {
    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->vertex = vertex;
    newNode->next = NULL;
    return newNode;
}

Graph *createGraph(int numVertices) {
    Graph *graph = (Graph*)malloc(sizeof(Graph));
    graph->numVertices = numVertices;

    graph->array = (AdjList*)malloc(numVertices * sizeof(AdjList));

    for (int i = 0; i < numVertices; i++) {
        graph->array[i].head = NULL;
    }

    return graph;
}

void addEdge(Graph *graph, int startVertex, int endVertex) {
    // 添加边,将邻接顶点添加到对应的链表中
    Node *newNode = createNode(endVertex);
    newNode->next = graph->array[startVertex].head;
    graph->array[startVertex].head = newNode;

    // 如果是有向图,只需上述代码
    // 如果是无向图,还需添加下面一行代码
    newNode = createNode(startVertex);
    newNode->next = graph->array[endVertex].head;
    graph->array[endVertex].head = newNode;
}

void printGraph(Graph *graph) {
    printf("Adjacency List:\n");
    for (int i = 0; i < graph->numVertices; i++) {
        Node *temp = graph->array[i].head;
        printf("Vertex %d: ", i);
        while (temp) {
            printf("%d -> ", temp->vertex);
            temp = temp->next;
        }
        printf("NULL\n");
    }
}

int main() {
    int numVertices = 5;
    Graph *graph = createGraph(numVertices);

    addEdge(graph, 0, 1);
    addEdge(graph, 1, 2);
    addEdge(graph, 2, 3);
    addEdge(graph, 3, 4);
    addEdge(graph, 4, 0);

    printGraph(graph);

    return 0;
}

在上述代码中,首先定义了Node结构体,表示邻接表中的链表节点;AdjList结构体,表示邻接表中的链表头节点;Graph结构体,表示图。createNode函数用于创建节点;createGraph函数用于创建图,并初始化邻接表;addEdge函数用于添加边,将邻接顶点添加到对应的链表中;printGraph函数用于打印邻接表。

以上两种算法分别适用于不同的场景,邻接矩阵适用于稠密图,邻接表适用于稀疏图。根据实际需求选择合适的存储算法可以提高程序的效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1265531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt路径和Anaconda中QT路径冲突(ubuntu系统)

最近做一个项目需要配置QT库&#xff0c;本项目配置环境如下&#xff1a; Qt version 5 Operating system, version and so on ubuntu 20.04 Description 之前使用过anaconda环境安装过QT5&#xff0c;所以在项目中CMakeLists文件中使用find_package时候&#xff0c;默认使用An…

C#,数值计算——插值和外推,径向基函数插值(RBF_inversemultiquadric)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class RBF_inversemultiquadric : RBF_fn { private double r02 { get; set; } public RBF_inversemultiquadric(double scale 1.0) { this.r02 Globals.SQR(scale); …

Spring Boot实现图片上传和展示

Spring Boot实现图片上传和展示 本文将介绍如何使用Spring Boot框架搭建后端服务&#xff0c;实现接收前端上传的图片并保存到resources/images目录下。同时&#xff0c;我们还将展示如何在前端编写一个HTML页面&#xff0c;实现上传图片和从resources/images目录下获取图片并…

PHP+vue+elementui高校学生社团信息管理系统o7q4a

社团是由高校用户依据兴趣爱好自愿组成&#xff0c;按照章程自主开展活动的用户组织。高校社团是实施素质教育的重要途径和有效方式&#xff0c;在加强校园文化建设、提高用户综合素质、引导用户适应社会、促进用户交流等方面发挥着重要作用&#xff0c;是新形势下有效凝聚用户…

[Python入门系列之十一]在windows上安装OpenCV

1-安装OpenCV 如果是python3.7–python3.9(已测试)&#xff0c;直接安装即可 注&#xff1a;conda需要先激活虚拟环境后再安装 pip install opencv-python如果安装速度慢&#xff0c;使用下面的指令&#xff1a; pip install opencv-python -i https://pypi.tuna.tsinghua.e…

AIGC-文生视频

stable diffusion&#xff1a; stable diffusion原理解读通俗易懂&#xff0c;史诗级万字爆肝长文&#xff0c;喂到你嘴里 - 知乎个人网站一、前言&#xff08;可跳过&#xff09;hello&#xff0c;大家好我是 Tian-Feng&#xff0c;今天介绍一些stable diffusion的原理&#…

Micropython STM32F4外部中断实验

Micropython STM32F4外部中断实验 &#x1f4cc;固件刷可参考前面一篇《STM32刷Micropython固件参考指南》&#x1f33f; 相关篇《Micropython STM32F4入门点灯》&#x1f4cd;固件下载&#xff1a;https://micropython.org/download/?mcustm32f4&#x1f516;本例程基于STM32…

「C++」红黑树的插入(手撕红黑树系列)

&#x1f4bb;文章目录 &#x1f4c4;前言红黑树概念红黑树的结构红黑树节点的定义红黑树的定义红黑树的调整 红黑树的迭代器迭代器的声明operator( )opeartor--( ) 完整代码 &#x1f4d3;总结 &#x1f4c4;前言 作为一名程序员相信你一定有所听闻红黑树的大名&#xff0c;像…

【区块链】产品经理的NFT初探

常见的FT如比特币&#xff08;BTC&#xff09;&#xff0c;以太币&#xff08;ETH&#xff09;等&#xff0c;两个代币之间是完全可替换的。而NFT具有唯一性&#xff0c;不可以互相替换。本文作者对NET的发展现状、相关协议、应用场景等方面进行了分析&#xff0c;一起来看一下…

修复debain/ Ubuntu 中的“密钥存储在旧版 trust.gpg 密钥环中”问题

如果您在 Ubuntu 22.04 及更高版本中使用 PPA 或添加外部存储库&#xff0c;您很可能会看到如下消息&#xff1a; W: https://packagecloud.io/slacktechnologies/slack/debian/dists/jessie/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg),…

springcloud nacos配置优先级研究及配置管理最佳实践

目录 背景工具版本SpringCloud配置存放位置及相应优先级代码中nacosjar包外挂 多种配置共同存在时的优先级项目配置管理最佳实践无nacos的情况有nacos的情况 参考文献 背景 公司有很多应用是基于SpringBoot/SpringCloud开发。由于在配置文件中经常会涉及数据库账号密码之类的敏…

Gson的用法详解

一、简介 Gson&#xff08;又称Google Gson&#xff09;是Google公司发布的一个开放源代码的Java库&#xff0c;主要用途为序列化Java对象为JSON字符串&#xff0c;或反序列化JSON字符串成Java对象。 Gson官网&#xff1a;gson Gson源码地址&#xff1a;google/gson 二、依赖…

Long-Context下LLM模型架构全面介绍

深度学习自然语言处理 原创作者&#xff1a;cola 随着ChatGPT的快速发展&#xff0c;基于Transformer的大型语言模型(LLM)为人工通用智能(AGI)铺平了一条革命性的道路&#xff0c;并已应用于知识库、人机界面和动态代理等不同领域。然而&#xff0c;存在一个普遍的限制:当前许多…

Linux处理文件常见命令

目录 1 cp 2 rm 3 zip与unzip 3.1 zip 3.2 unzip 4 cd 5 ls 6 chmod 7 scp 7.1 文件在你操作的机器上&#xff0c;你要传给另一个机器 7.1.1 文件 7.1.2 文件夹 7.2 文件在另一个机器上&#xff0c;你要把文件搞到你操作的机器上 7.2.1 文件 7.2.…

NX二次开发UF_CURVE_create_arc_3point 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_create_arc_3point Defined in: uf_curve.h int UF_CURVE_create_arc_3point(tag_t point1, tag_t point2, tag_t point3, UF_CURVE_limit_p_t limit_p [ 2 ] , tag_t supp…

开发知识点-CSS样式

CSS样式 fontCSS 外边距 —— 围绕在元素边框的空白区域# linear-gradient() ——创建一个线性渐变的 "图像"# transform ——旋转 元素![在这里插入图片描述](https://img-blog.csdnimg.cn/20191204100321698.png)# rotate() [旋转] # 边框 (border) —— 围绕元素内…

无分类编址 CIDR

在域名系统出现之后的第一个十年里&#xff0c;基于分类网络进行地址分配和路由IP数据包的设计就已明显显得可扩充性不足&#xff08;参见RFC 1517&#xff09;。为了解决这个问题&#xff0c;互联网工程工作小组在1993年发布了一新系列的标准——RFC 1518和RFC 1519——以定义…

时尚和美容网站的技术 SEO:提示和最佳实践

如果你对美容和时尚感兴趣&#xff0c;做了一个网站&#xff0c;但不知道如何在上面做技术SEO&#xff1f;此外&#xff0c;时尚和美容网站的技术 SEO 没有任何特别的指南&#xff01; 我们听到了你的声音&#xff01;但首先&#xff0c;请记住&#xff0c;技术性SEO不是在一两…

Docker监控Weave Scope的安装和使用

1.本地安装Weave Scope 1&#xff09;创建文件夹。 mkdir /usr/local/bin/scope 2&#xff09;从本地上传文件。 rz scope.bin以资源形式已上传到文章开篇。 3&#xff09;修改scope.bin文件为可执行文件。 chmod 755 /usr/local/bin/scope/scope.bin 4&#xff09;执行sco…

使用 SwiftUI 创建一个灵活的选择器

文章目录 前言可选择协议自定义化FlexiblePicker 逻辑FlexiblePicker 视图总结 前言 最近&#xff0c;在我正在开发一个在 Dribbble 上找到的设计的 SwiftUI 实现时&#xff0c;我想到了一个点子&#xff0c;可以通过一些酷炫的筛选器扩展该项目以缩小结果列表。 我决定筛选视…