0
点赞
收藏
分享

微信扫一扫

线上模型准确率估计——在没有标签的测试数据上估计模型准确率

爱做梦的夏夏 2024-11-09 阅读 7

文末有代码和安装教程。

绳子游戏:https://icode.inscode.cc/

更多精彩内容:https://inscode.csdn.net/@2301_81482480

喜欢不要忘记关注呀~

深入解析链表:原理与实践

链表是一种基本的数据结构,它在计算机科学中有着广泛的应用。链表的核心思想是通过节点(Node)来存储数据,每个节点包含数据部分和指向下一个节点的指针。这种结构使得链表在插入和删除操作上具有很高的效率。本文将详细探讨链表的实现方法,并通过一个具体的链表头文件 linked_list.h 来进行分析。

链表的基本概念

链表是一种线性数据结构,由一系列节点组成。每个节点包含两个部分:数据部分和指针部分。数据部分存储实际的数据,而指针部分指向链表中的下一个节点。链表的第一个节点称为头节点(head),最后一个节点称为尾节点(tail),尾节点的指针部分通常为空(nullptr)。

链表可以分为单向链表、双向链表和循环链表等多种类型。单向链表是最简单的链表结构,每个节点只有一个指向下一个节点的指针。双向链表则每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。循环链表则是一种首尾相连的链表结构。

链表的操作

链表的主要操作包括插入、删除、查找和遍历等。插入操作通常在链表的头部或尾部进行,删除操作则是根据节点的值或位置来删除节点。查找操作则是根据节点的值来查找节点,遍历操作则是从头节点开始依次访问每个节点。

链表头文件 linked_list.h 分析

下面是一个简单的链表头文件 linked_list.h 的实现:

#ifndef LINKED_LIST_H
#define LINKED_LIST_H

#include <iostream>

struct Node {
int data;
Node* next;
Node(int data) : data(data), next(nullptr) {}
};

class LinkedList {
public:
LinkedList();
~LinkedList();
void insert(int data);
void remove(int data);
Node* search(int data);
void print();
int size() const;
bool isEmpty() const;
Node* getHead() const;
Node* getTail() const;

private:
Node* head;
};

#endif

节点结构 Node

节点结构 Node 是链表的基本单元,包含两个成员变量:data 和 nextdata 用于存储节点的数据,next 是一个指向下一个节点的指针。节点的构造函数用于初始化节点的数据部分和指针部分。

struct Node {
int data;
Node* next;
Node(int data) : data(data), next(nullptr) {}
};

链表类 LinkedList

链表类 LinkedList 包含链表的主要操作,如插入、删除、查找等。链表类的主要成员变量是 head,它是一个指向链表头节点的指针。

构造函数和析构函数

链表的构造函数用于初始化链表,将头节点指针设为 nullptr。析构函数用于释放链表占用的内存,通过遍历链表并删除每个节点来实现。

LinkedList::LinkedList() : head(nullptr) {}

LinkedList::~LinkedList() {
Node* current = head;
while (current) {
Node* next = current->next;
delete current;
current = next;
}
}
插入操作

插入操作可以在链表的头部或尾部进行。下面是链表尾部插入的实现方法。首先创建一个新的节点,然后遍历链表找到尾节点,将尾节点的 next 指针指向新节点。

void LinkedList::insert(int data) {
Node* newNode = new Node(data);
if (!head) {
head = newNode;
} else {
Node* current = head;
while (current->next) {
current = current->next;
}
current->next = newNode;
}
}
删除操作

删除操作是根据节点的值来删除节点。首先判断链表是否为空,如果链表为空则直接返回。如果头节点的值等于要删除的值,则将头节点指针指向下一个节点,并删除原头节点。否则,遍历链表找到要删除的节点的前一个节点,将前一个节点的 next 指针指向要删除节点的下一个节点,并删除要删除的节点。

void LinkedList::remove(int data) {
if (!head) {
return;
}
if (head->data == data) {
Node* temp = head;
head = head->next;
delete temp;
return;
}
Node* current = head;
while (current->next && current->next->data != data) {
current = current->next;
}
if (current->next) {
Node* temp = current->next;
current->next = current->next->next;
delete temp;
}
}
查找操作

查找操作是根据节点的值来查找节点。首先判断链表是否为空,如果链表为空则返回 nullptr。否则,遍历链表找到值等于要查找的值的节点,并返回该节点的指针。

Node* LinkedList::search(int data) {
Node* current = head;
while (current) {
if (current->data == data) {
return current;
}
current = current->next;
}
return nullptr;
}
遍历操作

遍历操作是从头节点开始依次访问每个节点。首先判断链表是否为空,如果链表为空则直接返回。否则,遍历链表并输出每个节点的数据。

void LinkedList::print() {
Node* current = head;
while (current) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
}
获取链表大小和判断链表是否为空

获取链表大小是通过遍历链表并计数每个节点来实现的。判断链表是否为空则是通过判断头节点指针是否为 nullptr 来实现的。

int LinkedList::size() const {
int count = 0;
Node* current = head;
while (current) {
count++;
current = current->next;
}
return count;
}

bool LinkedList::isEmpty() const {
return head == nullptr;
}
获取链表头节点和尾节点

获取链表头节点是直接返回头节点指针。获取链表尾节点则是通过遍历链表找到最后一个节点并返回其指针。

Node* LinkedList::getHead() const {
return head;
}

Node* LinkedList::getTail() const {
Node* current = head;
Node* tail = nullptr;
while (current) {
tail = current;
current = current->next;
}
return tail;
}

链表的应用场景

链表在计算机科学中有着广泛的应用,以下是一些常见的应用场景:

动态数组

链表可以作为一种动态数组来实现,它可以在运行时动态地增加或减少数组的大小。与静态数组相比,链表在插入和删除操作上具有更高的效率。

栈和队列

链表可以用来实现栈和队列等数据结构。栈是一种后进先出(LIFO)的数据结构,队列是一种先进先出(FIFO)的数据结构。链表可以方便地实现这两种数据结构。

链表的其他应用

链表还可以用于实现哈希表、图等数据结构,以及在算法设计中作为辅助数据结构。

链表的优缺点

优点

  1. 动态大小:链表的大小可以在运行时动态调整,不需要预先分配固定大小的内存。
  2. 高效的插入和删除:链表在插入和删除操作上具有很高的效率,特别是在链表的头部或尾部进行操作时。
  3. 内存利用率高:链表可以充分利用内存空间,不需要预先分配固定大小的内存。

缺点

  1. 访问效率低:链表在访问操作上效率较低,需要通过遍历链表来找到特定的节点。
  2. 内存开销大:链表需要额外的内存空间来存储节点的指针。
  3. 实现复杂:链表的操作实现相对复杂,需要考虑节点的创建、删除和内存释放等问题。

总结

链表是一种基本且重要的数据结构,它在计算机科学中有着广泛的应用。链表的核心思想是通过节点来存储数据,每个节点包含数据部分和指向下一个节点的指针。链表的主要操作包括插入、删除、查找和遍历等。链表在插入和删除操作上具有很高的效率,但在访问操作上效率较低。链表可以用于实现动态数组、栈、队列等多种数据结构,并在算法设计中作为辅助数据结构。通过本文的分析,我们可以更好地理解链表的原理和实现方法,并在实际编程中灵活运用链表。

参考文献

  1. 数据结构与算法分析(C++版),Mark Allen Weiss 著,机械工业出版社。
  2. 计算机科学的数据结构与算法分析,Aho、Hopcroft、Ullman 著,机械工业出版社。
  3. C++ Primer(第5版),Stanley B. Lippman、Josée Lajoie、Barbara E. Moo 著,电子工业出版社。

希望这篇文章能够帮助您更好地理解链表的原理和实现方法。如果您有任何问题或需要进一步的帮助,请随时联系我。

代码及安装教程

// linked_list.h
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#pragma once

#include <iostream>

struct Node {
int data;
Node* next;
Node(int data) : data(data), next(nullptr) {}
};

class LinkedList {
public:
LinkedList();
~LinkedList();

void insert(int data);
void remove(int data);
Node* search(int data);
void print();

int size() const;
bool isEmpty() const;
Node* getHead() const;
Node* getTail() const;

private:
Node* head;
};

LinkedList::LinkedList() : head(nullptr) {}

LinkedList::~LinkedList() {
Node* current = head;
while (current) {
Node* next = current->next;
delete current;
current = next;
}
}

void LinkedList::insert(int data) {
Node* newNode = new Node(data);
if (!head) {
head = newNode;
} else {
Node* current = head;
while (current->next) {
current = current->next;
}
current->next = newNode;
}
}

void LinkedList::remove(int data) {
if (!head) {
return;
}

if (head->data == data) {
Node* temp = head;
head = head->next;
delete temp;
return;
}

Node* current = head;
while (current->next && current->next->data!= data) {
current = current->next;
}

if (current->next) {
Node* temp = current->next;
current->next = current->next->next;
delete temp;
}
}

Node* LinkedList::search(int data) {
Node* current = head;
while (current) {
if (current->data == data) {
return current;
}
current = current->next;
}
return nullptr;
}

void LinkedList::print() {
Node* current = head;
while (current) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
}

int LinkedList::size() const {
int count = 0;
Node* current = head;
while (current) {
count++;
current = current->next;
}
return count;
}

bool LinkedList::isEmpty() const {
return head == nullptr;
}

Node* LinkedList::getHead() const {
return head;
}

Node* LinkedList::getTail() const {
Node* current = head;
Node* tail = nullptr;
while (current) {
tail = current;
current = current->next;
}
return tail;
}
#endif

将本代码复制到你想安装这个头文件的文件夹里 ,文件名linked_list.h。(一定注意.h是后缀名!!!弄错就运行不聊啦!!!有问题私信我就行~~)

然后就可以通过

#include "linked_list.h"

来调用了。

结语

在本文中,我们深入探讨了链表这一基本且重要的数据结构。链表通过节点来存储数据,每个节点包含数据部分和指向下一个节点的指针。这种结构使得链表在插入和删除操作上具有很高的效率。我们详细分析了链表头文件 linked_list.h 的实现方法,包括节点的定义、链表类的构造函数和析构函数、插入操作、删除操作、查找操作、遍历操作以及获取链表大小和判断链表是否为空等方法。

链表在计算机科学中有着广泛的应用,可以用于实现动态数组、栈、队列等多种数据结构,并在算法设计中作为辅助数据结构。通过本文的分析,我们可以更好地理解链表的原理和实现方法,并在实际编程中灵活运用链表。

链表虽然是一种基本的数据结构,但其应用场景广泛,掌握链表的使用对于学习数据结构和算法具有重要意义。希望这篇文章能够帮助您更好地理解链表的原理和实现方法。如果您有任何问题或需要进一步的帮助,请随时联系我。

最后,感谢您对编程和计算机科学的热爱与追求。愿您在编程的道路上越走越远,不断探索和发现新的知识。链表只是计算机科学中的冰山一角,希望您能够继续深入学习,掌握更多的数据结构和算法,成为一名优秀的程序员。

祝您学习愉快,编程进步!

举报

相关推荐

0 条评论