王道考研--》单链表课后习题C语言代码实现(冲刺)

news2024/9/24 11:27:09

        考研是许多计算机科学专业学生追求高学历、寻求更好就业前景的途径。在考研过程中,数据结构是一个非常重要的科目,而代码实现题更是其中的难点之一。在这篇文章中,我们将探讨如何通过实现数据结构代码问题来提升考研成绩。无论您是否有编程经验,本文将为您提供一些简单但实用的技巧,帮助您应对考研中遇到的数据结构题目。让我们一起踏上这个挑战性的学习旅程吧!

目录

初识单链表

第一题)递归删除不带头节点链表中指定值

第二题)带头节点链表删除指定值

第三题)反向输出链表值

第四题) 带头节点的单链表删除最小值结点

第五题)求两链表交集

第六题)单链表排序

第七题)删除重复结点

第八题)删除绝对值相等的结点


初识单链表

        单链表是一种常见的基本数据结构,它由一系列节点组成,每个节点包含两部分:数据(即存储的元素)和指向下一个节点的引用(指针或链接)。单链表中的节点按照其在内存中的位置顺序连接起来,形成一个链式结构。

单链表中的第一个节点称为头节点,最后一个节点的指针部分指向一个空值(通常表示为 null),表示链表的结束。

单链表的特点

1)动态性: 单链表的长度可以动态地增加或减少,不需要预先指定大小。

2)插入与删除高效: 在单链表中,插入或删除元素时只需要修改节点之间的指针,时间复杂度为 O(1)。

3)随机访问效率低: 与数组不同,单链表中的元素并不是在连续的内存空间中存储的,因此难以通过索引进行快速访问,需要从头节点开始按顺序遍历,时间复杂度为 O(n)。

实现单链表通常包括以下步骤(C语言实现):

1)定义节点结构体
首先,需要定义一个结构体来表示链表的节点。这个结构体通常包含两部分:数据成员和指向下一个节点的指针成员。

2)节点的创建与初始化
可以通过动态内存分配(malloc 函数)来创建新的节点,并通过赋值操作对节点中的数据和指针进行初始化。

3)插入与删除节点
可以编写函数来实现在链表中插入新节点或删除现有节点的操作。这些操作通常涉及对节点之间的指针进行调整。

4)遍历与访问
为了能够访问链表中的所有节点,需要使用循环结构或递归来依次访问每个节点,并进行相应的操作。

5)释放内存
在链表不再需要时,需要确保释放所有节点所占用的内存,以避免内存泄漏。

具体代码实现如下

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

// 定义链表节点的结构体
struct Node {
    int data;
    struct Node* next;
};

// 在链表末尾插入新节点
void appendNode(struct Node** headRef, int newData) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    struct Node* last = *headRef;

    newNode->data = newData;
    newNode->next = NULL;

    if (*headRef == NULL) {
        *headRef = newNode;
        return;
    }

    while (last->next != NULL) {
        last = last->next;
    }

    last->next = newNode;
}

// 打印链表中的所有节点数据
void printList(struct Node* node) {
    while (node != NULL) {
        printf("%d -> ", node->data);
        node = node->next;
    }
    printf("NULL\n");
}

int main() {
    // 初始化头节点
    struct Node* head = NULL;

    // 在链表末尾依次插入节点
    appendNode(&head, 1);
    appendNode(&head, 2);
    appendNode(&head, 3);

    // 打印链表
    printf("Linked list: ");
    printList(head);

    return 0;
}

第一题)递归删除不带头节点链表中指定值

设计一个递归算法,删除不带头节点的单链表L中所有值为 x 的结点。

实现思路如下

首先:代码定义了一个单链表的数据结构,每个节点包含一个整型数据和一个指向下一个节点的指针。
然后:在deleteNodes函数中,首先检查链表是否为空。如果为空,则返回空。否则,递归调用deleteNodes函数,对链表的下一个节点进行删除操作。
接着:在deleteNodes函数中,如果当前节点的数据等于要删除的元素x,那么就删除当前节点。具体操作是,先保存下一个节点的指针,然后释放当前节点的内存,最后返回下一个节点的指针。
最后:在main函数中,首先获取用户输入的单链表长度和元素,然后调用deleteNodes函数删除指定元素,最后打印删除后的单链表结果。

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

struct Node {
    int data;
    struct Node* next;
};

struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("链表为空,请重新创建:\n");
        exit(1);
    }
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

void insertNode(struct Node** head, int data) {
    struct Node* newNode = createNode(data);
    if (*head == NULL) {
        *head = newNode;
        return;
    }
    struct Node* curr = *head;
    while (curr->next != NULL) {
        curr = curr->next;
    }
    curr->next = newNode;
}

struct Node* deleteNodes(struct Node* head, int x) {
    struct Node* prev = NULL;
    struct Node* curr = head;
    while (curr != NULL) {
        if (curr->data == x) {
            if (prev == NULL) {
                head = curr->next;
            }
            else {
                prev->next = curr->next;
            }
            free(curr);
            return head;
        }
        prev = curr;
        curr = curr->next;
    }
    return head;
}

void printList(struct Node* head) {
    while (head != NULL) {
        printf("%d ", head->data);
        head = head->next;
    }
    printf("\n");
}

int main() {
    struct Node* head = NULL;
    int n, data, x;

    printf("请输入单链表的长度: ");
    if (scanf_s("%d", &n) != 1 || n < 0) {
        printf("输入长度有误!请重新输入:\n");
        return 1;
    }

    printf("请输入单链表的元素: ");
    for (int i = 0; i < n; i++) {
        if (scanf_s("%d", &data) != 1 || data < 0) {
            printf("输入元素有误!请重新输入.\n");
            return 1;
        }
        insertNode(&head, data);
    }

    printf("请输入要删除的元素: ");
    if (scanf_s("%d", &x) != 1 || x < 0) {
        printf("删除元素有误!请重新删除.\n");
        return 1;
    }

    head = deleteNodes(head, x);

    printf("最终的单链表结果为: ");
    printList(head);

    return 0;
}

执行代码结果展示如下:

第二题)带头节点链表删除指定值

在带头节点的单链表 L 中,删除所有值为 x 的结点,并释放其空间,假设值为 x 的结点不唯一,试编写算法以实现上述操作。

实现思路如下

首先:我们定义了单链表的结点结构体,并创建了一个带头节点的单链表。

接着:我们实现了向单链表中插入新结点和删除单链表中所有值为 x 的结点的功能。

然后:在主函数中,我们首先输入单链表的结点个数和值,并将这些值插入到单链表中,输入要删除的结点值,并调用删除结点的函数。

最后:我们打印出删除后的单链表。这样就完成了整体代码的四个步骤。

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

// 定义单链表结点结构体
typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 创建带头节点的单链表
Node* createLinkedList() {
    Node* head = (Node*)malloc(sizeof(Node));
    head->next = NULL;
    return head;
}

// 向单链表中插入新结点
void insertNode(Node* head, int value) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;

    Node* p = head;
    while (p->next != NULL) {
        p = p->next;
    }
    p->next = newNode;
}

// 删除单链表中所有值为 x 的结点
void deleteNodes(Node* head, int x) {
    Node* p = head->next;
    Node* prev = head;

    while (p != NULL) {
        if (p->data == x) {
            Node* temp = p;
            prev->next = p->next;
            p = p->next;
            free(temp);
        }
        else {
            prev = p;
            p = p->next;
        }
    }
}

// 打印单链表
void printLinkedList(Node* head) {
    Node* p = head->next;
    while (p != NULL) {
        printf_s("%d ", p->data);
        p = p->next;
    }
    printf_s("\n");
}

int main() {
    Node* list = createLinkedList();

    // 输入单链表数据
    int n;
    printf_s("请输入单链表的结点个数:");
    scanf_s("%d", &n);

    printf_s("请输入单链表的结点值:\n");
    for (int i = 0; i < n; i++) {
        int value;
        scanf_s("%d", &value);
        insertNode(list, value);
    }

    // 输入要删除的结点值
    int x;
    printf_s("请输入要删除的结点值:");
    scanf_s("%d", &x);

    // 删除值为 x 的结点
    deleteNodes(list, x);

    // 打印删除后的单链表
    printf_s("删除后的单链表:");
    printLinkedList(list);

    return 0;
}

执行代码结果展示如下:

第三题)反向输出链表值

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

实现思路如下

首先:程序定义了一个Link结构体,用于表示链表的节点,每个节点包含一个整数数据和一个指向下一个节点的指针。

接着:在函数reverseOutput中,首先判断传入的链表节点指针是否为空,如果为空,则直接返回。否则,递归地调用reverseOutput函数,并传入该节点的下一个节点指针。这样可以先逆序输出链表后面的节点。

然后:在递归调用之后,打印当前节点的数据,用printf_s函数输出。

最后:在main函数中,首先读取用户输入的创建链表的节点个数。然后定义两个指针变量q和head,其中q用于指向链表的头指针,head用于指向最新的节点。接下来,通过循环创建链表的节点,每次循环创建一个新的节点,让head->next指向新节点,然后将head指向新节点,以保证head始终指向最新的节点。最后,将链表的最后一个节点的next指针置为NULL,将head重新指向q,即将head指向链表头节点。最后,调用reverseOutput函数输出逆序的链表元素。最后,返回0表示程序正常结束。

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

struct Link {
	int data;
	struct Link* next;
};

void reverseOutput(Link* p) {
	if (p == NULL) return;
	else {
		reverseOutput(p->next);
		printf_s("%d ", p->data);
	}
}

int main() {
	int n, data;
	printf_s("请输入创建链表的结点个数:");
	scanf_s("%d", &n);
	struct Link* q;
	struct Link* head = (struct Link*)malloc(sizeof(struct Link));
	head->next = NULL;
	q = head;
	for (int i = 0; i < n; i++)
	{
		struct Link* newP = (struct Link*)malloc(sizeof(struct Link));
		printf_s("请输入第 %d 个结点的值:",i+1);
		scanf_s("%d", &data);
		newP->data = data;
		newP->next = NULL;
		head->next = newP;
		head = head->next; // head要始终指向最新节点
	}
	head->next = NULL;
	head = q; // 最后head要指向头结点
	reverseOutput(head->next);
	return 0;
}

执行代码结果展示如下: 

第四题) 带头节点的单链表删除最小值结点

试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)

实现思路如下

首先:代码定义了一个链表结点结构体 Node,其中包含数据域 data 和指向下一个结点的指针next。

接着:通过createLinkedList函数创建了一个带头结点的单链表。在函数内部,我们使用malloc函数为头结点分配内存,并将头结点的next指针指向NULL,表示链表为空。

然后:使用insertNode函数向链表中插入新节点。该函数接受一个链表头结点指针head和要插入的值value作为参数。在函数内部,我们首先创建一个新的结点newNode,并为其分配内存。然后,我们遍历链表,找到链表的尾部结点,将新节点插入到尾部结点的next指针处。

最后:通过deleteMinNode函数删除链表中的最小值结点。该函数接受链表头结点指针head作为参数。在函数内部,我们使用两个指针prev和curr来遍历链表,找到最小值结点以及其前一个结点。然后,我们将最小值结点的前一个结点的`next`指针指向最小值结点的下一个结点,并释放最小值结点的内存。

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

// 定义链表结点结构体
typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 创建带头结点的单链表
Node* createLinkedList() {
    Node* head = (Node*)malloc(sizeof(Node));
    head->next = NULL;
    return head;
}

// 向链表中插入新节点
void insertNode(Node* head, int value) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;
    Node* curr = head;
    while (curr->next != NULL) {
        curr = curr->next;
    }
    curr->next = newNode;
}

// 删除最小值结点
void deleteMinNode(Node* head) {
    if (head == NULL || head->next == NULL) {
        return;
    }
    Node* prev = head;
    Node* curr = head->next;
    Node* minPrev = prev; // 最小值结点的前一个结点
    Node* minNode = curr; // 最小值结点
    while (curr != NULL) {
        if (curr->data < minNode->data) {
            minPrev = prev;
            minNode = curr;
        }
        prev = curr;
        curr = curr->next;
    }
    minPrev->next = minNode->next;
    free(minNode);
}

// 打印链表
void printLinkedList(Node* head) {
    if (head == NULL || head->next == NULL) {
        printf("链表为空\n");
        return;
    }
    Node* curr = head->next;
    while (curr != NULL) {
        printf("%d ", curr->data);
        curr = curr->next;
    }
    printf("\n");
}

int main() {
    Node* L = createLinkedList();

    int n;  // 链表长度
    printf("请输入链表的长度:");
    scanf_s("%d", &n);

    printf("请输入链表的元素:\n");
    for (int i = 0; i < n; i++) {
        int value;
        scanf_s("%d", &value);
        insertNode(L, value);
    }

    printf("原始链表:");
    printLinkedList(L);

    deleteMinNode(L);

    printf("删除最小值结点后的链表:");
    printLinkedList(L);

    return 0;
}

执行代码结果展示如下:  

第五题)求两链表交集

已知两个链表A和B分别表示两个集合,其元素递增排序。编制函数,求A与B的交集,并存放于A链表中。

实现思路如下

首先:通过createLinkedList函数创建了两个带头结点的单链表A和B。该函数分配了内存空间,并将头结点的next指针指向NULL,表示链表为空。

接着:使用scanf_s函数获取用户输入的整数n和m,分别表示链表A和B的长度。

然后:调用findIntersection函数,传入A链表和B链表作为参数。该函数用于找到A链表和B链表的交集,并将结果存放在A链表中。

最后:通过printLinkedList函数分别打印出原始的A和B链表以及交集结果。

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

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

// 创建带头结点的单链表
Node* createLinkedList() {
    Node* head = (Node*)malloc(sizeof(Node));
    head->next = NULL;
    return head;
}

// 向链表中插入新节点
void insertNode(Node* head, int value) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;
    Node* curr = head;
    while (curr->next != NULL) {
        curr = curr->next;
    }
    curr->next = newNode;
}

// 求两个递增排序链表的交集,并将结果存放于A链表中
void findIntersection(Node* A, Node* B) {
    Node* currA = A->next;
    Node* currB = B->next;
    Node* prevA = A;
    Node* temp;

    while (currA != NULL && currB != NULL) {
        if (currA->data < currB->data) {
            prevA->next = currA->next;
            temp = currA;
            currA = currA->next;
            free(temp);
        }
        else if (currA->data > currB->data) {
            currB = currB->next;
        }
        else {
            prevA = currA;
            currA = currA->next;
            currB = currB->next;
        }
    }

    while (currA != NULL) {
        prevA->next = currA->next;
        temp = currA;
        currA = currA->next;
        free(temp);
    }
}

// 打印链表
void printLinkedList(Node* head) {
    if (head == NULL || head->next == NULL) {
        printf("链表为空\n");
        return;
    }
    Node* curr = head->next;
    while (curr != NULL) {
        printf("%d ", curr->data);
        curr = curr->next;
    }
    printf("\n");
}

int main() {
    Node* A = createLinkedList();
    Node* B = createLinkedList();

    int n, m; // A链表长度和B链表长度
    printf("请输入A链表的长度:");
    scanf_s("%d", &n);
    printf("请输入A链表的元素(递增排序):\n");
    for (int i = 0; i < n; i++) {
        int value;
        scanf_s("%d", &value);
        insertNode(A, value);
    }

    printf("请输入B链表的长度:");
    scanf_s("%d", &m);
    printf("请输入B链表的元素(递增排序):\n");
    for (int i = 0; i < m; i++) {
        int value;
        scanf_s("%d", &value);
        insertNode(B, value);
    }

    printf("原始A链表:");
    printLinkedList(A);
    printf("原始B链表:");
    printLinkedList(B);

    findIntersection(A, B);

    printf("A与B的交集结果:");
    printLinkedList(A);

    return 0;
}

执行代码结果展示如下: 

第六题)单链表排序

有一个带头结点的单链表L,设计一个算法使其元素递增有序。

实现思路如下

首先:定义了链表节点结构体ListNode,包含数据域和指向下一个节点的指针。

接着:实现了创建新节点的函数createNewNode,用于分配内存并初始化新节点。

然后:实现了将元素插入有序链表的函数insertInOrder,根据元素大小找到合适的位置插入新节点,并保持链表的有序性。

最后:在主函数中,通过用户输入创建带头结点的链表L,并调用insertInOrder将输入的元素按递增顺序插入链表中,最后打印排列后的链表内容。

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

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

// 创建新节点
ListNode* createNewNode(int data) {
    ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 将元素插入有序链表中
void insertInOrder(ListNode** head, int data) {
    ListNode* newNode = createNewNode(data);

    // 如果链表为空或者新节点的值小于头结点的值,则将新节点作为头结点
    if (*head == NULL || data < (*head)->data) {
        newNode->next = *head;
        *head = newNode;
    }
    else {
        ListNode* curr = *head;

        // 找到适当的位置插入新节点
        while (curr->next != NULL && data > curr->next->data) {
            curr = curr->next;
        }

        newNode->next = curr->next;
        curr->next = newNode;
    }
}

// 打印链表的内容
void printLinkedList(ListNode* head) {
    ListNode* curr = head;
    while (curr != NULL) {
        printf("%d ", curr->data);
        curr = curr->next;
    }
    printf("\n");
}

// 从键盘读取用户输入的整数
int readInt() {
    int num;
    scanf_s("%d", &num);
    return num;
}

// 主函数
int main() {
    // 创建带头结点的链表L
    ListNode* L = createNewNode(0);
    printf("请输入链表L的元素个数:");
    int n = readInt();
    for (int i = 0; i < n; i++) {
        printf("请输入第%d个元素:", i + 1);
        int data = readInt();
        insertInOrder(&L, data);
    }

    printf("排列后的链表L: ");
    printLinkedList(L->next);

    return 0;
}

执行代码结果展示如下: 

第七题)删除重复结点

设计一个算法完成以下功能:在单链表中删除重复结点。

实现思路如下

首先:定义了链表节点的结构体。

接着:实现了创建新节点的函数和打印链表的函数。

然后:实现了删除重复节点的函数。该函数通过遍历链表,对于每一个节点,再次遍历链表来找到并删除与当前节点数据相同的节点。

最后:实现了主函数。在主函数中,首先要求用户输入链表的元素个数和具体数值,然后根据输入创建一个单链表。接着调用删除重复节点的函数,再打印出删除重复节点后的链表。最后,释放链表内存。

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

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

// 创建新节点
ListNode* createNewNode(int data) {
    ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 打印链表
void printList(ListNode* head) {
    ListNode* current = head;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

// 删除重复节点
void removeDuplicates(ListNode* head) {
    if (head == NULL) {
        return;
    }

    ListNode* current = head;
    while (current != NULL) {
        ListNode* runner = current;
        while (runner->next != NULL) {
            if (runner->next->data == current->data) {
                ListNode* duplicate = runner->next;
                runner->next = runner->next->next;
                free(duplicate);
            }
            else {
                runner = runner->next;
            }
        }
        current = current->next;
    }
}

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

// 主函数
int main() {
    int n;
    printf("请输入链表元素个数:");
    scanf_s("%d", &n);

    ListNode* head = NULL;
    ListNode* tail = NULL;

    printf("请输入链表元素值:");
    for (int i = 0; i < n; i++) {
        int data;
        scanf_s("%d", &data);

        ListNode* newNode = createNewNode(data);

        if (head == NULL) {
            head = newNode;
            tail = newNode;
        }
        else {
            tail->next = newNode;
            tail = newNode;
        }
    }

    printf("原链表:");
    printList(head);

    removeDuplicates(head);

    printf("删除重复节点后的链表:");
    printList(head);

    // 释放链表内存
    freeList(head);

    return 0;
}

执行代码结果展示如下: 

第八题)删除绝对值相等的结点

设计一个算法完成以下功能:在单链表中删除绝对值相等的元素。

实现思路如下

首先:定义了一个链表节点的结构体,并实现了创建新节点、打印链表、删除绝对值相等节点和释放链表内存的函数。

接着:主函数中要求用户输入链表元素的个数和具体数值,然后根据输入创建一个单链表。

然后:调用removeAbsoluteDuplicates函数来删除链表中绝对值相等的节点。

最后:打印出删除绝对值相等节点后的链表,并释放链表的内存。

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

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

// 创建新节点
ListNode* createNewNode(int data) {
    ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 打印链表
void printList(ListNode* head) {
    ListNode* current = head;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

// 删除绝对值相等节点
void removeAbsoluteDuplicates(ListNode* head) {
    if (head == NULL) {
        return;
    }

    ListNode* current = head;
    while (current != NULL && current->next != NULL) {
        ListNode* runner = current;

        while (runner->next != NULL) {
            if (abs(runner->next->data) == abs(current->data)) {
                ListNode* duplicate = runner->next;
                runner->next = runner->next->next;
                free(duplicate);
            }
            else {
                runner = runner->next;
            }
        }
        current = current->next;
    }
}

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

// 主函数
int main() {
    int n;
    printf("请输入链表元素个数:");
    scanf_s("%d", &n);

    ListNode* head = NULL;
    ListNode* tail = NULL;

    printf("请输入链表元素值:");
    for (int i = 0; i < n; i++) {
        int data;
        scanf_s("%d", &data);

        ListNode* newNode = createNewNode(data);

        if (head == NULL) {
            head = newNode;
            tail = newNode;
        }
        else {
            tail->next = newNode;
            tail = newNode;
        }
    }

    printf("原链表:");
    printList(head);

    removeAbsoluteDuplicates(head);

    printf("删除绝对值相等节点后的链表:");
    printList(head);

    // 释放链表内存
    freeList(head);

    return 0;
}

执行代码结果展示如下: 

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

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

相关文章

重温经典struts1之自定义转换器及注册的两种方式(Servlet,PlugIn)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 Struts的ActionServlet接收用户在浏览器发送的请求&#xff0c;并将用户输入的数据&#xff0c;按照FormBean中定义的数据类型&#xff0c;赋值给FormBean中每个变量&a…

YOLOv8改进 | 2023注意力篇 | HAttention(HAT)超分辨率重建助力小目标检测 (全网首发)

一、本文介绍 本文给大家带来的改进机制是HAttention注意力机制&#xff0c;混合注意力变换器&#xff08;HAT&#xff09;的设计理念是通过融合通道注意力和自注意力机制来提升单图像超分辨率重建的性能。通道注意力关注于识别哪些通道更重要&#xff0c;而自注意力则关注于图…

【Python动漫系列】小香香(完整代码)

文章目录 环境需求完整代码程序分析系列文章环境需求 python3.11.4及以上版本PyCharm Community Edition 2023.2.5pyinstaller6.2.0(可选,这个库用于打包,使程序没有python环境也可以运行,如果想发给好朋友的话需要这个库哦~)【注】 python环境搭建请见:https://want595.…

《论文阅读28》Unsupervised 3D Shape Completion through GAN Inversion

GAN&#xff0c;全称GenerativeAdversarialNetworks&#xff0c;中文叫生成式对抗网络。顾名思义GAN分为两个模块&#xff0c;生成网络以及判别网络&#xff0c;其中 生成网络负责根据随机向量产生图片、语音等内容&#xff0c;产生的内容是数据集中没有见过的&#xff0c;也可…

C语言—每日选择题—Day56

指针相关博客 打响指针的第一枪&#xff1a;指针家族-CSDN博客 深入理解&#xff1a;指针变量的解引用 与 加法运算-CSDN博客 第一题 1. 以下叙述中正确的是&#xff08;&#xff09; A&#xff1a;\0 表示字符 0 B&#xff1a;"a" 表示一个字符常量 C&#xff1a;表…

机器学习与深度学习傻傻分不清?快来!

导读&#xff1a;本文探讨机器学习和深度学习之间的关键区别和相互联系&#xff0c;目的是为大家提供一个清晰的框架&#xff0c;帮助大家理解这两种技术的特点、应用场景以及选择适当方法的依据。&#xff08;理论辨析&#xff0c;无实践代码&#xff0c;放心食用&#xff09;…

js之零碎工具(四)

一、数组的去重 简单类型的去重 let arr [1, 2, 2, 3, 4, 4, 5]; let uniqueArr [...new Set(arr)]; console.log(uniqueArr); // 输出&#xff1a;[1, 2, 3, 4, 5]在这个例子中&#xff0c;我们首先创建了一个新的 Set 对象&#xff0c;并将数组 arr 作为参数传递给 Set 的…

令人惊叹的代码技巧

在编程世界中&#xff0c;有一些令人惊叹的代码技巧和巧妙的实现方式。以下是一些我见过的令人印象深刻的代码技巧&#xff1a; 函数式编程魔法&#xff1a; 使用函数式编程的一些特性&#xff0c;比如高阶函数、匿名函数和Lambda表达式&#xff0c;可以使代码更为简洁、易读。…

C# 使用NUnit进行单元测试

写在前面 NUnit是一个开源的.Net单元测试框架&#xff0c;经常被用来在.Net体系下做白盒测试。 NUnit.org GitHub 本文记录一个简单的使用NUnit进行单元测试的完整流程。 代码实现 新建一个目标类库NUnitTester&#xff0c;添加待测试的类文件&#xff0c;内容如下&#…

hyper-v ubuntu2204指定静态ip地址

虚拟机静态IP设置 虚拟机每次重新启动&#xff0c;都会动态分配IP&#xff0c;这导致我们无法使用一个固定的ip连接到虚拟机内部。解决该问题的最直接有效的办法就是给虚拟机绑定2张网卡&#xff0c;一张用于连接外网、一张用于连接内网。 init 0 关机&#xff0c;也可以从管…

Python正则表达式与replace函数,空格问题轻松搞定!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在数据处理中&#xff0c;清理文本数据是一个常见而关键的任务。空格是文本中常见的干扰项之一&#xff0c;可能存在于字符串的开头、结尾或中间。Python提供了正则表达式和replace函数两种强大的工具&#xff0…

Unity中Shader平移变换

文章目录 前言方式一&#xff1a;对顶点本地空间下的坐标进行相加平移1、在属性面板定义一个四维变量记录在 xyz 上平移多少。2、在常量缓冲区进行申明3、在顶点着色器中&#xff0c;在进行其他坐标转化之前&#xff0c;对模型顶点本地空间下的坐标进行转化4、我们来看看效果 方…

Pixel Nerf代码阅读

Input&#xff1a; 图像的 分辨率是 300*400&#xff1b; 每个场景里面有 49张 Training 的图像。 SB&#xff1a; scene batch 场景的个数&#xff1b; 4 NV&#xff1a; number input &#xff0c;每个场景的视角&#xff0c;也就是图像的数量&#xff1b; 49 每条光线首先…

被我们忽略的HttpSession线程安全问题

1. 背景 最近在读《Java concurrency in practice》(Java并发实战)&#xff0c;其中1.4节提到了Java web的线程安全问题时有如下一段话&#xff1a; Servlets and JPSs, as well as servlet filters and objects stored in scoped containers like ServletContext and HttpSe…

牛客BC115 超级圣诞树

万众瞩目 在上一篇我们介绍了一个圣诞树的打印&#xff0c;而这道题与上次不同的是他的基本单位是一直在变的 我建议先把上一个搞懂在写这道题这个。 牛客网BC114 圣诞树-CSDN博客 ok那么正文开始 题目如下 今天是圣诞节&#xff0c;牛牛要打印一个漂亮的圣诞树送给想象中…

Flink Table API 与 SQL 编程整理

Flink API总共分为4层这里主要整理Table API的使用 Table API是流处理和批处理通用的关系型API&#xff0c;Table API可以基于流输入或者批输入来运行而不需要进行任何修改。Table API是SQL语言的超集并专门为Apache Flink设计的&#xff0c;Table API是Scala和Java语言集成式…

【数据结构】并查集的简单实现,合并,查找(C++)

文章目录 前言举例&#xff1a; 一、1.构造函数2.查找元素属于哪个集合FindRoot3.将两个集合归并成一个集合Union4.查找集合数量SetCount 二、源码 前言 需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规…

Unity的UI界面——Text/Image

编辑UI界面时&#xff0c;要先切换到2d界面 &#xff08;3d项目的话&#xff09; 1.Text控件 Text控件的相关属性&#xff1a; Character:&#xff08;字符&#xff09; Font&#xff1a;字体 Font Style&#xff1a;字体样式 Font Size&#xff1a;字体大小 Line Spac…

c语言力扣题目:消失的数字(有关时间复杂度O(N²)O(N))以及对异或操作符的更深入的理解(如何用人脑的十进制去考量二进制)

目录 Way One :暴力求解,时间复杂度为 O(N) 代码1 Way Two : 时间复杂度限制到 O(N) 代码及其详解 如题 Way One :暴力求解,时间复杂度为 O(N) 大体思路:比如这里我们需要处理的整型数组是"3,0,1",我们可以用冒泡排序或者 qsort函数将他从大到小进行排序成"…

【SQL】根据年份,查询每个月的数据量

根据年份&#xff0c;查询每个月的数据量 一种 WITH Months AS (SELECT 1 AS Month UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION…