软考:软件设计师考试数据结构知识点详解
文章目录
- 1. 引言
- 1.1 数据结构的重要性
- 1.2 软件设计师考试中数据结构的考察目标
- 2. 基本概念和术语
- 2.1 数据结构的定义
- 2.2 算法和数据结构的关系
- 2.3 抽象数据类型(ADT)
- 3. 线性结构
- 3.1 数组
- 3.1.1 数组的定义和特点
- 3.1.2 数组的存储结构
- 3.1.3 数组的优缺点
- 3.2 链表
- 3.2.1 链表的定义和特点
- 3.2.2 单链表
- 3.2.3 双向链表
- 3.2.4 循环链表
- 3.2.5 链表的优缺点
- 4. 栈和队列
- 4.1 栈
- 4.1.1 栈的定义和特点
- 4.1.2 栈的实现方法
- 4.1.3 栈的应用
- 4.2 队列
- 4.2.1 队列的定义和特点
- 4.2.2 队列的实现方法
- 4.2.3 循环队列
- 4.2.4 队列的应用
- 5. 树形结构
- 5.1 树的基本概念
- 5.1.1 树的定义
- 5.1.2 树的术语
- 5.2 二叉树
- 5.2.1 二叉树的定义和特点
- 5.2.2 二叉树的遍历
- 5.2.3 二叉搜索树
- 5.3 平衡树
- 5.3.1 平衡树的定义
- 5.3.2 AVL树
- 5.3.3 红黑树
- 6. 图形结构
- 6.1 图的基本概念
- 6.1.1 图的定义
- 6.1.2 图的术语
- 6.2 图的存储结构
- 6.2.1 邻接矩阵
- 6.2.2 邻接表
- 6.3 图的遍历
- 6.3.1 深度优先搜索(DFS)
- 6.3.2 广度优先搜索(BFS)
- 7. 查找和排序
- 7.1 查找
- 7.1.1 顺序查找
- 7.1.2 二分查找
- 7.1.3 哈希查找
- 7.2 排序
- 7.2.1 冒泡排序
- 7.2.2 选择排序
- 7.2.3 插入排序
- 7.2.4 快速排序
- 7.2.5 归并排序
- 8. 算法分析
- 8.1 算法复杂度
- 8.1.1 时间复杂度
- 8.1.2 空间复杂度
- 8.2 算法设计技巧
- 8.2.1 递归
- 8.2.2 分治
- 8.2.3 动态规划
- 8.2.4 贪心算法
1. 引言
在软件设计师考试中,数据结构是核心考察内容之一。掌握数据结构对于理解计算机算法、优化程序性能以及解决复杂问题至关重要。本章将介绍数据结构的重要性和在软件设计师考试中的考察目标。
1.1 数据结构的重要性
数据结构是计算机存储、组织数据的方式,它直接影响到程序的运行效率。合理的数据结构可以提高数据处理的效率,节省存储空间,简化算法设计。在软件开发中,选择合适的数据结构对于提升软件性能和质量具有重要意义。
1.2 软件设计师考试中数据结构的考察目标
软件设计师考试旨在评估考生对数据结构基本概念、原理和应用的理解和掌握程度。考试内容通常包括:
- 数据结构的基本概念和术语
- 线性结构(数组、链表、栈、队列)
- 树形结构(二叉树、平衡树)
- 图形结构(图的存储和遍历)
- 查找和排序算法
- 算法分析
- 数据结构的应用
通过这些内容的考察,测试考生是否具备设计、实现和优化数据结构的能力,以及能否将数据结构应用于解决实际问题。
2. 基本概念和术语
理解数据结构的基本概念和术语是掌握数据结构的前提。本章将介绍数据结构的定义、算法与数据结构的关系以及抽象数据类型(ADT)。
2.1 数据结构的定义
数据结构是计算机中存储、组织数据的方式,它能够使数据组织得更加有结构,以便可以更高效地存取和修改数据。数据结构包括数据元素之间的关系和数据元素的存储方式。
2.2 算法和数据结构的关系
算法是解决问题的方法,而数据结构是算法操作的对象。算法的效率很大程度上取决于所使用的数据结构。良好的数据结构可以提高算法的效率,简化算法的设计。反之,不当的数据结构可能导致算法效率低下,甚至无法解决问题。
示例:
- 使用数组实现的排序算法通常比使用链表实现的更高效,因为数组支持随机访问,而链表只支持顺序访问。
2.3 抽象数据类型(ADT)
抽象数据类型(Abstract Data Type,ADT)是数据结构的一种数学模型,它定义了一组数据和一组操作这些数据的操作,而无需指定数据的存储细节。ADT强调数据的逻辑结构和行为特性,而不是物理结构。
常见的抽象数据类型包括:
- 栈(Stack):后进先出(LIFO)的数据结构。
- 队列(Queue):先进先出(FIFO)的数据结构。
- 列表(List):有序的数据元素集合。
- 树(Tree):层次结构的数据结构。
- 图(Graph):由顶点和边组成的数据结构。
ADT的优点在于它提供了一种抽象层,使得我们可以在不关心具体实现细节的情况下,使用数据结构和算法。这种抽象性有助于提高代码的可读性、可维护性和可重用性。
示例:
// 栈的抽象数据类型定义
class Stack {
public:void push(int value); // 入栈操作int pop(); // 出栈操作bool isEmpty(); // 判断栈是否为空
};
在本章中,我们介绍了数据结构的基本概念和术语,包括数据结构的定义、算法与数据结构的关系以及抽象数据类型(ADT)。理解这些基本概念对于深入学习数据结构至关重要。在下一章中,我们将探讨线性结构,包括数组、链表、栈和队列。
3. 线性结构
线性结构是数据结构中最基础的部分,其中的元素之间存在一对一的线性关系。本章将详细介绍线性结构中的数组、链表、栈和队列。
3.1 数组
数组是一种最基本的线性结构,它由相同类型的元素组成,这些元素在内存中是连续存放的。
3.1.1 数组的定义和特点
- 定义:数组是由具有相同类型的若干元素组成的有序集合。
- 特点:
- 随机访问:可以通过索引快速访问任意元素。
- 固定大小:数组的大小在创建时确定,之后不能改变。
- 内存连续:数组元素在内存中是连续存放的。
3.1.2 数组的存储结构
数组在内存中是一块连续的存储空间,每个元素的存储地址可以通过基地址加上偏移量计算得到。
示例代码(C++):
int arr[5] = {10, 20, 30, 40, 50};
cout << "Element at index 2: " << arr[2] << endl; // 输出:30
3.1.3 数组的优缺点
- 优点:
- 访问速度快:可以通过索引直接访问任意元素。
- 内存利用率高:元素在内存中连续存放,没有额外的存储开销。
- 缺点:
- 大小固定:数组的大小在创建时确定,之后不能改变。
- 插入和删除效率低:在数组中插入或删除元素需要移动大量元素。
3.2 链表
链表是一种由一系列节点组成的线性结构,每个节点包含数据域和指针域,指针域指向下一个节点。
3.2.1 链表的定义和特点
- 定义:链表是由一系列节点组成的有序集合,每个节点包含数据域和指针域。
- 特点:
- 动态大小:链表的大小可以根据需要动态变化。
- 非连续存储:链表元素在内存中不一定是连续存放的。
3.2.2 单链表
单链表是链表的一种,每个节点包含一个指针,指向下一个节点。
示例代码(C++):
struct Node {int data;Node* next;
};Node* head = new Node{10, nullptr};
head->next = new Node{20, nullptr};
head->next->next = new Node{30, nullptr};
3.2.3 双向链表
双向链表是链表的一种,每个节点包含两个指针,分别指向前一个节点和后一个节点。
示例代码(C++):
struct Node {int data;Node* prev;Node* next;
};Node* head = new Node{10, nullptr, nullptr};
head->next = new Node{20, head, nullptr};
head->next->next = new Node{30, head->next, nullptr};
3.2.4 循环链表
循环链表是链表的一种,最后一个节点的指针指向第一个节点,形成一个环。
示例代码(C++):
struct Node {int data;Node* next;
};Node* head = new Node{10, nullptr};
head->next = new Node{20, nullptr};
head->next->next = new Node{30, head}; // 形成环
3.2.5 链表的优缺点
- 优点:
- 动态大小:链表的大小可以根据需要动态变化。
- 插入和删除效率高:在链表中插入或删除元素只需要改变指针。
- 缺点:
- 访问速度慢:不能直接访问任意元素,需要从头节点开始遍历。
- 内存利用率低:每个节点需要额外的存储空间来存放指针。
在本章中,我们详细介绍了线性结构中的数组和链表。数组是一种基础的线性结构,具有随机访问的特点,但大小固定,插入和删除效率低。链表是一种动态的线性结构,插入和删除效率高,但访问速度慢。在下一章中,我们将探讨栈和队列。
4. 栈和队列
栈和队列是两种重要的线性结构,它们在数据的存取方式上有各自的特点和应用场景。
4.1 栈
4.1.1 栈的定义和特点
- 定义:栈是一种遵循后进先出(Last In First Out, LIFO)原则的线性结构。
- 特点:
- 只能在一端进行插入和删除操作,这一端被称为栈顶。
- 插入操作称为入栈(push),删除操作称为出栈(pop)。
4.1.2 栈的实现方法
栈可以用数组或链表来实现。数组实现的栈具有随机访问的特点,而链表实现的栈则具有更好的灵活性。
示例代码(C++ 使用数组实现栈):
#include <iostream>
#include <stack>int main() {std::stack<int> s;s.push(1);s.push(2);s.push(3);while (!s.empty()) {std::cout << s.top() << " ";s.pop();}return 0;
}
4.1.3 栈的应用
栈在许多算法和程序设计中都有应用,如表达式求值、括号匹配、函数调用等。
示例:括号匹配
#include <iostream>
#include <stack>
#include <string>bool isBalanced(const std::string& expr) {std::stack<char> s;for (char c : expr) {if (c == '(') {s.push(c);} else if (c == ')') {if (s.empty() || s.top() != '(') {return false;}s.pop();}}return s.empty();
}int main() {std::string expr = "((a+b)*(c-d))";if (isBalanced(expr)) {std::cout << "The expression is balanced." << std::endl;} else {std::cout << "The expression is not balanced." << std::endl;}return 0;
}
4.2 队列
4.2.1 队列的定义和特点
- 定义:队列是一种遵循先进先出(First In First Out, FIFO)原则的线性结构。
- 特点:
- 插入操作通常在一端进行,称为队尾。
- 删除操作通常在另一端进行,称为队头。
4.2.2 队列的实现方法
队列可以用数组或链表来实现。数组实现的队列需要处理循环队列的问题,而链表实现的队列则更加灵活。
示例代码(C++ 使用链表实现队列):
#include <iostream>
#include <list>template<typename T>
class Queue {
private:std::list<T> elements;public:void enqueue(const T& element) {elements.push_back(element);}T dequeue() {if (elements.empty()) {throw std::runtime_error("Queue is empty");}T frontElement = elements.front();elements.pop_front();return frontElement;}bool isEmpty() const {return elements.empty();}
};int main() {Queue<int> q;q.enqueue(1);q.enqueue(2);q.enqueue(3);while (!q.isEmpty()) {std::cout << q.dequeue() << " ";}return 0;
}
4.2.3 循环队列
循环队列是一种特殊的队列,它使用固定大小的数组来存储元素,并使用两个指针(通常称为头指针和尾指针)来指示队列的前端和后端。
示例代码(C++ 实现循环队列):
#include <iostream>
#include <vector>class CircularQueue {
private:std::vector<int> data;int head;int tail;int capacity;public:CircularQueue(int size) : capacity(size), head(0), tail(0) {data.resize(capacity);}bool enqueue(int value) {if ((tail + 1) % capacity == head) {return false; // Queue is full}data[tail] = value;tail = (tail + 1) % capacity;return true;}int dequeue() {if (head == tail) {throw std::runtime_error("Queue is empty");}int value = data[head];head = (head + 1) % capacity;return value;}bool isEmpty() const {return head == tail;}
};int main() {CircularQueue q(3);q.enqueue(1);q.enqueue(2);std::cout << q.dequeue() << " "; // 输出 1q.enqueue(3);std::cout << q.dequeue() << " "; // 输出 2std::cout << q.dequeue() << " "; // 输出 3return 0;
}
4.2.4 队列的应用
队列在许多算法和程序设计中都有应用,如任务调度、缓冲处理、广度优先搜索等。
在本章中,我们详细介绍了栈和队列的定义、特点、实现方法和应用。栈是一种后进先出的数据结构,常用于处理递归、回溯等问题;队列是一种先进先出的数据结构,常用于任务调度、缓冲处理等场景。在下一章中,我们将探讨树形结构,包括二叉树、平衡树等。
5. 树形结构
树形结构是一类重要的非线性数据结构,它模拟了树的层次关系,具有丰富的应用场景。
5.1 树的基本概念
5.1.1 树的定义
树是一种由节点(Node)组成的数据结构,具有以下特点:
- 有且仅有一个特定的称为根(Root)的节点。
- 除根节点外,其余节点可分为若干个互不相交的子树(Subtree)。
- 每个节点最多有一个前驱节点(即父节点),可以有零个或多个后继节点(即子节点)。
5.1.2 树的术语
- 节点的度(Degree):节点拥有的子节点数目。
- 树的度:树中所有节点的度的最大值。
- 叶子节点(Leaf):度为0的节点。
- 内部节点(Internal Node):至少有一个子节点的节点。
- 路径长度:从根节点到某一节点的路径上节点数目。
- 树的高度(Height):树中最长路径的长度。
- 树的深度:节点的深度是从根节点到该节点所经历的边的数目。
5.2 二叉树
二叉树是树形结构中的一种特殊形式,每个节点最多有两个子节点,通常称为左子节点和右子节点。
5.2.1 二叉树的定义和特点
- 定义:二叉树的每个节点最多有两个子节点,分别称为左子节点和右子节点。
- 特点:
- 左子节点的值总是小于或等于父节点的值。
- 右子节点的值总是大于或等于父节点的值。
5.2.2 二叉树的遍历
二叉树的遍历是指按照某种顺序访问树中的所有节点。常见的遍历方式包括:
- 前序遍历(Pre-order):先访问根节点,然后递归地进行前序遍历左子树,最后递归地进行前序遍历右子树。
- 中序遍历(In-order):先递归地进行中序遍历左子树,然后访问根节点,最后递归地进行中序遍历右子树。
- 后序遍历(Post-order):先递归地进行后序遍历左子树,然后递归地进行后序遍历右子树,最后访问根节点。
- 层序遍历(Level-order):按照从上到下、从左到右的顺序逐层访问节点。
示例代码(C++ 实现二叉树的前序遍历):
#include <iostream>
#include <vector>struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};void preOrderTraversal(TreeNode* root) {if (root == nullptr) return;std::cout << root->val << " ";preOrderTraversal(root->left);preOrderTraversal(root->right);
}int main() {TreeNode* root = new TreeNode(1);root->left = new TreeNode(2);root->right = new TreeNode(3);root->left->left = new TreeNode(4);root->left->right = new TreeNode(5);std::cout << "Pre-order traversal: ";preOrderTraversal(root);return 0;
}
5.2.3 二叉搜索树
二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树,其中每个节点都大于或等于其左子树上的所有节点,并且小于或等于其右子树上的所有节点。
示例代码(C++ 实现二叉搜索树的插入):
#include <iostream>struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};TreeNode* insertBST(TreeNode* root, int val) {if (root == nullptr) {return new TreeNode(val);}if (val < root->val) {root->left = insertBST(root->left, val);} else if (val > root->val) {root->right = insertBST(root->right, val);}return root;
}int main() {TreeNode* root = nullptr;root = insertBST(root, 4);insertBST(root, 2);insertBST(root, 6);insertBST(root, 1);insertBST(root, 3);insertBST(root, 5);// 构建的二叉搜索树为:// 4// / \// 2 6// / \ / \// 1 3 5return 0;
}
5.3 平衡树
平衡树是一种特殊的二叉搜索树,其中任何节点的两个子树的高度差不超过1,以确保树的高度最小化,从而提高搜索、插入和删除操作的效率。
5.3.1 平衡树的定义
平衡树需要在每次插入或删除操作后进行调整,以保持树的平衡。
5.3.2 AVL树
AVL树(Adelson-Velsky and Landis Tree)是一种自平衡二叉搜索树,其中任何节点的两个子树的高度差不超过1。
5.3.3 红黑树
红黑树是一种自平衡二叉搜索树,每个节点都有一个颜色属性(红或黑),并且通过一系列的旋转和重新着色操作来保持树的平衡。
在本章中,我们详细介绍了树形结构,包括树的基本概念、二叉树的定义和特点、二叉树的遍历、二叉搜索树以及平衡树。在下一章中,我们将探讨图形结构,包括图的基本概念、图的存储结构和图的遍历。
6. 图形结构
图形结构是表示对象之间关系的一种数据结构,它由顶点(节点)和边组成。图在许多领域都有应用,如网络、路径规划、社交网络分析等。
6.1 图的基本概念
6.1.1 图的定义
图(Graph)是由顶点(Vertex)集合和边(Edge)集合组成的一种数据结构,其中边表示顶点之间的关系。
6.1.2 图的术语
- 顶点(Vertex):图中的节点,表示对象。
- 边(Edge):连接两个顶点的线,表示对象之间的关系。
- 有向图(Digraph):边有方向的图。
- 无向图(Undirected Graph):边没有方向的图。
- 邻接(Adjacent):两个顶点之间存在边。
- 度(Degree):顶点的邻接边数。在有向图中,分为入度(指向该顶点的边数)和出度(从该顶点出发的边数)。
- 路径(Path):图中的一系列顶点,其中每对相邻顶点间都有一条边。
- 环(Cycle):起点和终点相同的路径。
6.2 图的存储结构
图的存储结构主要有两种:邻接矩阵和邻接表。
6.2.1 邻接矩阵
邻接矩阵是一个二维数组,用于表示图中顶点之间的邻接关系。矩阵的行和列对应图中的顶点,如果两个顶点之间有边,则矩阵中相应的元素为1,否则为0。
示例代码(C++ 使用邻接矩阵表示图):
#include <iostream>
#include <vector>using namespace std;const int INF = 0x3f3f3f3f; // 用INF代表两个点之间没有边void addEdge(vector<vector<int>>& graph, int from, int to) {graph[from][to] = 1; // 有向图// graph[to][from] = 1; // 无向图
}void printGraph(const vector<vector<int>>& graph) {int n = graph.size();for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {cout << graph[i][j] << " ";}cout << endl;}
}int main() {int n = 4;vector<vector<int>> graph(n, vector<int>(n, INF));addEdge(graph, 0, 1);addEdge(graph, 0, 2);addEdge(graph, 1, 2);addEdge(graph, 2, 0);addEdge(graph, 2, 3);printGraph(graph);return 0;
}
6.2.2 邻接表
邻接表是图的一种链式存储结构,它为每个顶点维护一个链表,链表中的每个节点代表与该顶点相邻的一个顶点。
示例代码(C++ 使用邻接表表示图):
#include <iostream>
#include <vector>
#include <list>using namespace std;class Graph {int V; // 顶点数vector<list<int>> adj; // 邻接表public:Graph(int V) : V(V), adj(V) {}void addEdge(int v, int w) {adj[v].push_back(w); // 添加边v->w// adj[w].push_back(v); // 如果是无向图,还需要添加边w->v}void printGraph() {for (int v = 0; v < V; ++v) {cout << "顶点 " << v << " -> ";for (auto i = adj[v].begin(); i != adj[v].end(); ++i)cout << *i << " ";cout << endl;}}
};int main() {Graph g(4);g.addEdge(0, 1);g.addEdge(0, 2);g.addEdge(1, 2);g.addEdge(2, 0);g.addEdge(2, 3);g.printGraph();return 0;
}
6.3 图的遍历
图的遍历是指按照某种顺序访问图中的所有顶点。常见的图遍历算法有深度优先搜索(DFS)和广度优先搜索(BFS)。
6.3.1 深度优先搜索(DFS)
深度优先搜索是一种递归算法,它从图中的某个顶点开始,沿着一条路径一直走到不能再走为止,然后回溯并沿着另一条路径继续搜索。
示例代码(C++ 实现DFS):
#include <iostream>
#include <vector>
#include <list>using namespace std;class Graph {int V; // 顶点数vector<list<int>> adj; // 邻接表void DFSUtil(int v, vector<bool>& visited); // 用于递归的辅助函数public:Graph(int V); // 构造函数void addEdge(int v, int w); // 添加边void DFS(int v); // 从顶点v开始进行DFS
};Graph::Graph(int V) {this->V = V;adj.resize(V);
}void Graph::addEdge(int v, int w) {adj[v].push_back(w); // 添加边v->w// adj[w].push_back(v); // 如果是无向图,还需要添加边w->v
}void Graph::DFSUtil(int v, vector<bool>& visited) {visited[v] = true;cout << v << " ";for (auto i = adj[v].begin(); i != adj[v].end(); ++i)if (!visited[*i])DFSUtil(*i, visited);
}void Graph::DFS(int v) {vector<bool> visited(V, false);DFSUtil(v, visited);
}int main() {Graph g(4);g.addEdge(0, 1);g.addEdge(0, 2);g.addEdge(1, 2);g.addEdge(2, 0);g.addEdge(2, 3);cout << "深度优先搜索(从顶点0开始): ";g.DFS(0);return 0;
}
6.3.2 广度优先搜索(BFS)
广度优先搜索是一种迭代算法,它从图中的某个顶点开始,首先访问所有相邻的顶点,然后依次访问这些相邻顶点的相邻顶点。
示例代码(C++ 实现BFS):
#include <iostream>
#include <vector>
#include <list>
#include <queue>using namespace std;class Graph {int V; // 顶点数vector<list<int>> adj; // 邻接表public:Graph(int V); // 构造函数void addEdge(int v, int w); // 添加边void BFS(int s); // 从顶点s开始进行BFS
};Graph::Graph(int V) {this->V = V;adj.resize(V);
}void Graph::addEdge(int v, int w) {adj[v].push_back(w); // 添加边v->w// adj[w].push_back(v); // 如果是无向图,还需要添加边w->v
}void Graph::BFS(int s) {vector<bool> visited(V, false);queue<int> queue;visited[s] = true;queue.push(s);while (!queue.empty()) {s = queue.front();cout << s << " ";queue.pop();for (auto i = adj[s].begin(); i != adj[s].end(); ++i)if (!visited[*i]) {visited[*i] = true;queue.push(*i);}}
}int main() {Graph g(4);g.addEdge(0, 1);g.addEdge(0, 2);g.addEdge(1, 2);g.addEdge(2, 0);g.addEdge(2, 3);cout << "广度优先搜索(从顶点0开始): ";g.BFS(0);return 0;
}
在本章中,我们详细介绍了图的基本概念、图的存储结构和图的遍历。图是一种强大的数据结构,可以表示复杂的关系和网络。在下一章中,我们将探讨查找和排序算法。
7. 查找和排序
查找和排序是数据结构中两个基本且重要的操作,它们在软件开发中有着广泛的应用。
7.1 查找
查找操作是指在数据结构中找到特定元素的过程。不同的数据结构和查找需求会导致不同的查找算法。
7.1.1 顺序查找
顺序查找(Sequential Search)是最简单直观的查找方法,它逐个检查数据结构中的每个元素,直到找到目标元素或搜索完整个数据结构。
示例代码(C+++ 实现顺序查找):
#include <iostream>
#include <vector>bool sequentialSearch(const std::vector<int>& data, int target) {for (int num : data) {if (num == target) {return true;}}return false;}int main() {std::vector<int> data = {2, 4, 6, 8, 10};int target = 6;if (sequentialSearch(data, target)) {std::cout << "Found " << target << std::endl;} else {std::cout << target << " not found" << std::endl;}return 0;}
7.1.2 二分查找
二分查找(Binary Search)是一种在有序数组中查找特定元素的高效算法。它通过不断地将待搜索的区间分成两半来缩小搜索范围。
示例代码(C+++ 实现二分查找):
#include <iostream>
#include <vector>
#include <algorithm>int binarySearch(const std::vector<int>& data, int target) {int left = 0;int right = data.size() - 1;while (left <= right) {int mid = left + (right - left) / 2;if (data[mid] == target) {return mid;} else if (data[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;
}int main() {std::vector<int> data = {2, 4, 6, 8, 10};int target = 6;int index = binarySearch(data, target);if (index != -1) {std::cout << "Found " << target << " at index " << index << std::endl;} else {std::cout << target << " not found" << std::endl;}return 0;
}
7.1.3 哈希查找
哈希查找(Hash Search)利用哈希表进行快速查找。哈希表通过哈希函数将元素映射到表中的位置,从而实现平均时间复杂度为O(1)的查找。
示例代码(C+++ 使用 unordered_map 实现哈希查找):
#include <iostream>
#include <unordered_map>bool hashSearch(const std::unordered_map<int, std::string>& hashTable, int key) {auto it = hashTable.find(key);if (it != hashTable.end()) {std::cout << "Found: " << it->second << std::endl;return true;}std::cout << key << " not found" << std::endl;return false;
}int main() {std::unordered_map<int, std::string> hashTable = {{1, "one"}, {2, "two"}, {3, "three"}};int key = 2;hashSearch(hashTable, key);return 0;
}
7.2 排序
排序是将数据结构中的元素按照一定的顺序重新排列的过程。排序算法在数据处理中非常重要。
7.2.1 冒泡排序
冒泡排序(Bubble Sort)是一种简单的排序算法,它重复地遍历要排序的数列,比较每对相邻元素,如果它们的顺序错误就把它们交换过来。
示例代码(C+++ 实现冒泡排序):
#include <iostream>
#include <vector>
#include <algorithm>void bubbleSort(std::vector<int>& data) {bool swapped;do {swapped = false;for (size_t i = 1; i < data.size(); ++i) {if (data[i - 1] > data[i]) {std::swap(data[i - 1], data[i]);swapped = true;}}} while (swapped);
}int main() {std::vector<int> data = {64, 34, 25, 12, 22, 11, 90};bubbleSort(data);std::cout << "Sorted array: ";for (int num : data) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
7.2.2 选择排序
选择排序(Selection Sort)是一种简单直观的排序算法,它的工作原理是首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置。
示例代码(C+++ 实现选择排序):
#include <iostream>
#include <vector>void selectionSort(std::vector<int>& data) {for (size_t i = 0; i < data.size() - 1; ++i) {int min_idx = i;for (size_t j = i + 1; j < data.size(); ++j) {if (data[j] < data[min_idx]) {min_idx = j;}}std::swap(data[min_idx], data[i]);}
}int main() {std::vector<int> data = {64, 25, 12, 22, 11};selectionSort(data);std::cout << "Sorted array: ";for (int num : data) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
7.2.3 插入排序
插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
示例代码(C+++ 实现插入排序):
#include <iostream>
#include <vector>void insertionSort(std::vector<int>& data) {for (size_t i = 1; i < data.size(); ++i) {int key = data[i];int j = i - 1;while (j >= 0 && data[j] > key) {data[j + 1] = data[j];--j;}data[j + 1] = key;}
}int main() {std::vector<int> data = {9, 5, 1, 4, 3};insertionSort(data);std::cout << "Sorted array: ";for (int num : data) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
7.2.4 快速排序
快速排序(Quick Sort)是一种高效的排序算法,采用分治策略来把一个序列分为较小的两个子序列。
示例代码(C++ 实现快速排序):
#include <iostream>
#include <vector>void quickSort(std::vector<int>& data, int low, int high) {if (low < high) {int pi = partition(data, low, high);quickSort(data, low, pi - 1);quickSort(data, pi + 1, high);}
}int partition(std::vector<int>& data, int low, int high) {int pivot = data[high];int i = (low - 1);for (int j = low; j <= high - 1; j++) {if (data[j] < pivot) {i++;std::swap(data[i], data[j]);}}std::swap(data[i + 1], data[high]);return (i + 1);
}int main() {std::vector<int> data = {10, 7, 8, 9, 1, 5};int n = data.size();quickSort(data, 0, n - 1);std::cout << "Sorted array: ";for (int num : data) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
7.2.5 归并排序
归并排序(Merge Sort)是建立在归并操作上的一种有效的排序算法,采用分治法的一个应用。
示例代码(C++ 实现归并排序):
#include <iostream>
#include <vector>void merge(std::vector<int>& data, int left, int mid, int right) {std::vector<int> temp(right - left + 1);int i = left; int j = mid + 1; int k = 0;while (i <= mid && j <= right) {if (data[i] <= data[j]) {temp[k++] = data[i++];} else {temp[k++] = data[j++];}}while (i <= mid) {temp[k++] = data[i++];}while (j <= right) {temp[k++] = data[j++];}for (i = left, k = 0; i <= right; ++i, ++k) {data[i] = temp[k];}
}void mergeSort(std::vector<int>& data, int left, int right) {if (left < right) {int mid = left + (right - left) / 2;mergeSort(data, left, mid);mergeSort(data, mid + 1, right);merge(data, left, mid, right);}
}int main() {std::vector<int> data = {12, 11, 13, 5, 6, 7};mergeSort(data, 0, data.size() - 1);std::cout << "Sorted array: ";for (int num : data) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
在本章中,我们详细介绍了查找和排序算法,包括顺序查找、二分查找、哈希查找以及冒泡排序、选择排序、插入排序、快速排序和归并排序。这些算法在软件开发中有着广泛的应用,掌握它们对于提高程序性能和解决实际问题非常重要。在下一章中,我们将探讨算法分析。
8. 算法分析
算法分析是评估算法性能的重要手段,它帮助我们理解算法在不同情况下的表现,从而选择最合适的算法解决问题。
8.1 算法复杂度
算法复杂度是衡量算法执行时间或空间需求与输入规模之间关系的量度。它通常用大O符号表示,描述算法在最坏情况下的性能。
8.1.1 时间复杂度
时间复杂度描述了算法执行时间随输入规模增长的变化趋势。常见的时间复杂度包括:
- 常数时间:(O(1))
- 线性时间:(O(n))
- 对数时间:(O(\log n))
- 线性对数时间:(O(n \log n))
- 平方时间:(O(n^2))
- 指数时间:(O(2^n))
8.1.2 空间复杂度
空间复杂度描述了算法执行过程中所需存储空间随输入规模增长的变化趋势。它同样使用大O符号表示。
8.2 算法设计技巧
算法设计技巧是构建高效算法的方法论,它们可以帮助我们设计出更优秀的算法。
8.2.1 递归
递归是一种通过函数自我调用解决问题的方法。它适用于可以分解为相似子问题的问题。
示例代码(C++ 实现递归计算阶乘):
int factorial(int n) {if (n <= 1) return 1;return n * factorial(n - 1);
}
8.2.2 分治
分治策略是将问题分解为更小的子问题,递归地解决子问题,然后将结果合并以得到原问题的解。
示例代码(C++ 实现分治算法计算数组元素和):
int getSum(int arr[], int l, int r) {if (l == r)return arr[l];int mid = (l + r) / 2;return getSum(arr, l, mid) + getSum(arr, mid + 1, r);
}
8.2.3 动态规划
动态规划是一种通过将问题分解为重叠子问题并存储子问题的解来避免重复计算的方法。
示例代码(C++ 实现动态规划计算斐波那契数列):
int fibonacci(int n) {if (n <= 1) return n;int dp[n + 1];dp[0] = 0, dp[1] = 1;for (int i = 2; i <= n; i++)dp[i] = dp[i - 1] + dp[i - 2];return dp[n];
}
8.2.4 贪心算法
贪心算法在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。
示例代码(C++ 实现贪心算法解决活动选择问题):
#include <iostream>
#include <vector>
#include <algorithm>struct Activity {int start, end, index;
};bool compareActivity(Activity a, Activity b) {return a.end < b.end;
}void printMaxActivities(std::vector<Activity>& activities) {std::sort(activities.begin(), activities.end(), compareActivity);int i = 0;std::cout << "Selected activities are \n";for (int j = 1; j < activities.size(); j++) {if (activities[j].start >= activities[i].end) {std::cout << "(" << activities[j].start << ", "<< activities[j].end << ") ";i = j;}}
}int main() {std::vector<Activity> activities = {{1, 2, 0}, {3, 4, 1}, {0, 6, 2}, {5, 7, 3}, {8, 9, 4}};int n = activities.size();printMaxActivities(activities);return 0;
}
在本章中,我们详细介绍了算法分析的基本概念和几种常见的算法设计技巧。算法分析帮助我们评估算法的性能,而算法设计技巧则指导我们设计出更高效的算法。在下一章中,我们将探讨数据结构的应用。
相关文章:
软考:软件设计师考试数据结构知识点详解
文章目录 1. 引言1.1 数据结构的重要性1.2 软件设计师考试中数据结构的考察目标 2. 基本概念和术语2.1 数据结构的定义2.2 算法和数据结构的关系2.3 抽象数据类型(ADT) 3. 线性结构3.1 数组3.1.1 数组的定义和特点3.1.2 数组的存储结构3.1.3 数组的优缺点…...
11前端项目总结----详情页放大镜和轮播图
商品详情页 DOM元素尺寸和位置相关属性1. 尺寸相关属性2.位置相关属性3.鼠标事件相关位置属性 放大镜排他Swiper和组件通信 DOM元素尺寸和位置相关属性 1. 尺寸相关属性 ①offsetWidth/offsetHeight:内容宽度/高度paddingborder(滚动条) ②c…...
Linux课程五课---Linux进程认识1
作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 🎂 作者介绍: 🎂🎂 🎂 🎉🎉🎉…...
Nacos简介—4.Nacos架构和原理一
大纲 1.Nacos的定位和优势 2.Nacos的整体架构 3.Nacos的配置模型 4.Nacos内核设计之一致性协议 5.Nacos内核设计之自研Distro协议 6.Nacos内核设计之通信通道 7.Nacos内核设计之寻址机制 8.服务注册发现模块的注册中心的设计原理 9.服务注册发现模块的注册中心的服务数…...
splitchunk(如何将指定文件从主包拆分为单独的js文件)
1. 说明 webpack打包会默认将入口文件引入依赖js打包为一个入口文件,导致这个文件会比较大,页面首次加载时造成加载时间较长 可通过splitchunk配置相应的规则,对匹配的规则打包为单独的js,减小入口js的体积 2. 示例 通过正则匹配ÿ…...
MCP+A2A协议终极指南:AI系统构建技术全解析(医疗/金融实战+Streamable HTTP代码详解)
简介 2025年,MCP协议与A2A协议成为AI系统互联的核心技术。本文从通信机制到企业级应用,结合Streamable HTTP、零信任安全、多模态处理等最新技术,提供Go/Python/Java多语言实战代码,覆盖医疗诊断、金融风控等场景。含15+完整案例、性能优化方案及安全架构设计,助你掌握下…...
关于定时任务原理
关于定时任务原理 计算机是怎么计时的关于本地定时任务实现小根堆实现时间轮实现 关于分布式任务的实现管理未来的执行时间点 今天来聊一下工作中经常使用的定时任务的底层实现原理 计算机是怎么计时的 计算机内部使用多种方式来计时,主要依赖于硬件时钟࿰…...
【vue3】购物车实战:从状态管理到用户体验的全流程实现
在电商项目中,购物车是核心功能之一,需要兼顾数据一致性、用户体验和逻辑复杂度。 本文结合 Vue3 Pinia 技术栈,详细讲解如何实现一个高效且易用的购物车系统,重点剖析 添加购物车 和 头部购物车预览 的核心逻辑与实现细节。 一…...
日本IT|UIUX主要的工作都是哪些?及职业前景
在日本IT行业中,UI/UX(用户界面/用户体验)设计的工作涵盖从用户研究到界面实现的全流程,尤其在数字化服务、电商、金融科技等领域需求旺盛。 本篇是UI/UX在日本的主要工作内容、行业特点及职业前景分析: 一、UI/UX的主…...
Tailwind CSS 实战:基于 Kooboo 构建企业官网页面(二)
基于上篇内容,继续完善企业官网页面: Tailwind CSS 实战:基于 Kooboo 构建企业官网页面(一) 3.3 服务亮点:用于展示企业主要的服务项 1. 整体结构: <section class"py-16">&…...
第7章 内部类与异常类
7.1 内部类 在一个类中定义另一个类,这样的类称为内部类,包含内部类的类称为内部类的外部类。 关系: 内部类的外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法。 内部类的类体中不可以声明类变量和…...
优先队列、堆笔记(算法第四版)
方法签名描述构造函数MaxPQ()创建一个优先队列MaxPQ(int max)创建一个初始容量为 max 的优先队列MaxPQ(Key[] a)用 a[] 中的元素创建一个优先队列普通方法void insert(Key v)向优先队列中插入一个元素Key max()返回最大元素Key delMax()删除并返回最大元素boolean isEmpty()返回…...
7.14 GitHub命令行工具测试实战:从参数解析到异常处理的全链路测试方案
GitHub命令行工具测试实战:从参数解析到异常处理的全链路测试方案 GitHub Sentinel Agent 用户界面设计与实现:测试命令行工具 关键词:命令行工具测试, 接口集成测试, 参数化测试, 异常处理测试, 测试覆盖率分析 1. 命令行工具测试架构设计 通过三层测试体系保障 CLI 工具…...
使用CubeMX新建USART1不定长接收工程
目录 1、新建板级支持包 2、修改中断服务函数 3、修改main.c文件 4、程序流程 新建工程的基本操作步骤参考这里:STM32CubeMX学习笔记(6)——USART串口使用_unused(huart)-CSDN博客 1、新建板级支持包 在本地保存新建工程的文件夹中新建Us…...
【C++QT】Layout 布局管理控件详解
文章目录 一、QVBoxLayout 垂直布局1.1 特点1.2 常用方法1.3 应用场景1.4 示例代码 二、QHBoxLayout 水平布局2.1 特点2.2 常用方法2.3 应用场景2.4 示例代码 三、QGridLayout 网格布局3.1 特点3.2 常用方法3.3 应用场景3.4 示例代码 四、QFormLayout 表单布局4.1 特点4.2 常用…...
w~嵌入式C语言~合集6
我自己的原文哦~ https://blog.51cto.com/whaosoft/13870384 一、开源MCU简易数字示波器项目 这是一款采用STC8A8K MCU制造的简单示波器,只有零星组件,易于成型。这些功能可以涵盖简单的测量: 该作品主要的规格如下: 单片机…...
坐标转换:从WGS-84到国内坐标系(GCJ-02BD-09)
目录 🍅点击这里查看所有博文 随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记…...
快速上手 MetaGPT
1. MetaGPT 简介 在当下的大模型应用开发领域,Agent 无疑是最炙手可热的方向,这也直接催生出了众多的 Agent 开发框架。在这之中, MetaGPT 是成熟度最高、使用最广泛的开发框架之一。 MetaGPT 是一款备受瞩目的多智能体开发框架,…...
「Docker已死?」:基于Wasm容器的新型交付体系如何颠覆十二因素应用宣言
一、容器技术的量子跃迁 1. 传统容器体系的测不准原理 某金融平台容器集群真实数据: 指标Docker容器Wasm容器差异度冷启动时间1200ms8ms150倍内存占用256MB6MB42倍镜像体积780MB12MB65倍内核调用次数2100次/s23次/s91倍 二、Wasm容器的超流体特性 1. 字节码的量子…...
有源晶振输出匹配电阻选择与作用详解
一、输出匹配电阻的核心作用 阻抗匹配 减少信号反射:当信号传输线阻抗(Z0)与负载阻抗不匹配时,会发生反射,导致波形畸变(如振铃、过冲)。 公式:反射系数Γ (Z_L - Z0) / (Z_L Z0)…...
Shell脚本-while循环应用案例
在Shell脚本编程中,while循环是一种非常有用的控制结构,适用于需要基于条件进行重复操作的场景。与for循环不同,while循环通常用于处理不确定次数的迭代或持续监控某些状态直到满足特定条件为止的任务。本文将通过几个实际的应用案例来展示如…...
【JavaScript】二十七、用户注册、登陆、登出
文章目录 1、案例:用户注册页面1.1 发送验证码1.2 验证用户名密码合法性1.3 已阅读并同意用户协议1.4 表单提交 2、案例:用户登陆页面2.1 tab切换2.2 登陆跳转2.3 登陆成功与登出 1、案例:用户注册页面 1.1 发送验证码 需求:用户…...
Vue中Axios实战指南:高效网络请求的艺术
Axios作为Vue生态中最流行的HTTP客户端,以其简洁的API和强大的功能成为前后端交互的首选方案。本文将带你深入掌握Axios在Vue项目中的核心用法和高级技巧。 一、基础配置 1. 安装与引入 npm install axios 2. 全局挂载(main.js) import …...
SAP-pp 怎么通过底表的手段查找BOM的全部ECN变更历史
表:ABOMITEMS,查询条件是MAST的STLNR (BOM清单) 如果要得到一个物料的详细ECN历史,怎么办? 先在MAST表查找BOM清单,然后根据BOM清单在ABOMITEMS表里面查询组件,根据查询组件的结果…...
数据需求管理办法有哪些?具体应如何应用?
目录 一、数据需求管理的定义 二、数据需求管理面临的问题 1.需求理解偏差 2.需求变更频繁 3.需求优先级难以确定 4.数据质量与需求不匹配 三、数据需求管理办法的具体流程 1.建立有效的沟通机制 2.规范需求变更管理流程 3.制定需求优先级评估标准 4.加强数据质量管…...
单片机 + 图像处理芯片 + TFT彩屏 复选框控件
复选框控件使用说明 一、控件概述 本复选框控件是一个适用于单片机图形界面的UI组件,基于单片机 RA8889/RA6809 TFT显示屏 GT911触摸屏开发。控件提供了丰富的功能和自定义选项,使用简单方便,易于移植。 主要特点: 支持可…...
塔能合作模式:解锁工厂能耗精准节能新路径
在工厂寻求能耗精准节能的道路上,除了先进的技术,合适的合作模式同样至关重要。塔能科技提供的能源合同管理(EMC)和交钥匙方式(EPC),为工厂节能项目的落地实施提供了有力支持,有效解…...
使用PHP对接印度股票市场数据
在本篇文章中,我们将介绍如何通过StockTV提供的API接口使用PHP语言来获取并处理印度股票市场的数据。我们将以查询公司信息、查看涨跌排行榜和实时接收数据为例,展示具体的操作流程。 准备工作 首先,请确保您已经从StockTV获得了API密钥&am…...
make学习三:书写规则
系列文章目录 Make学习一:make初探 Make学习二:makefile组成要素 文章目录 系列文章目录前言默认目标规则语法order-only prerequisites文件名中的通配符伪目标 Phony Targets没有 Prerequisites 和 recipe内建特殊目标名一个目标多条规则或多个目标共…...
Arduino 入门学习笔记(五):KEY实验
Arduino 入门学习笔记(五):KEY实验 开发板:正点原子ESP32S3 例程源码在文章顶部可免费下载(审核中…) 1. GPIO 输入功能使用 1.1 GPIO 输入模式介绍 在上一文章中提及到 pinMode 函数, 要对…...
Grok发布了Grok Studio 和 Workspaces两个强大的功能。该如何使用?如何使用Grok3 API?
最近Grok又更新了几个功能:Grok Studio 和 Workspaces。 其中 Grok Studio 主要功能包括: 代码执行:在预览标签中运行 HTML 片段、Python、JavaScript 等。 Google Drive 集成:附加并处理 Docs、Sheets、Slides等文件。 协作工…...
学习spark总结
一、Spark Core • 核心功能:基于内存计算的分布式计算框架,提供RDD弹性分布式数据集,支持转换(如map、filter)和动作(如collect、save)操作。 • 关键特性:高容错性(L…...
LeetCode 24 两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1: 输入:head [1,2,3,4] 输出:[2,1…...
Qt中的全局函数讲解集合(全)
目录 1.qAbs 2.qAsConst 3.qBound 4.qConstOverload 5.qEnvironmentVariable 6.qExchange 7.qFloatDistance 8.qInstallMessageHandler 在头文件<QtGlobal>中包含了Qt的全局函数,现在就这些全局函数一一详解。 1.qAbs 原型: template &…...
《明解C语言入门篇》读书笔记四
目录 第四章:程序的循环控制 第一节:do语句 do语句 复合语句(程序块)中的声明 读取一定范围内的值 逻辑非运算符 德摩根定律 德摩根定律 求多个整数的和及平均值 复合赋值运算符 后置递增运算符和后置递减运算符 练习…...
【每日随笔】文化属性 ② ( 高维度信息处理 | 强者思维形成 | 认知重构 | 资源捕获 | 进化路径 )
文章目录 一、高维度信息处理1、" 道 " - 高维度信息2、上士对待 " 道 " 的态度3、中士对待 " 道 " 的态度4、下士对待 " 道 " 的态度 二、形成强者思维1、认知重构 : 质疑本能 -> 信任惯性2、资源捕获 : 远神崇拜 -> 近身模仿3…...
terraform查看资源建的关联关系
一、使用 terraform graph 命令生成依赖关系图 该命令会生成资源间的依赖关系图(DOT 格式),需配合 Graphviz 工具可视化。 1. 安装 Graphviz # Ubuntu/Debian sudo apt-get install graphviz# MacOS brew install graphviz 2. 生成并查看…...
win11报错 ‘wmic‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件 的解决方案
方法一:检查环境变量 右键点击“此电脑”或“计算机”: 选择“属性”,然后点击“高级系统设置”。 进入环境变量设置: 在“系统属性”窗口中,点击“环境变量”。 检查Path变量: 在“系统变量”部分,找到并…...
监控易一体化运维:巡检管理,守护企业系统稳定的坚固防线
在数字化浪潮奔涌的当下,企业业务高度依赖信息技术系统,数据流量呈爆发式增长。从日常办公到核心业务运作,每一个环节都离不开稳定可靠的系统支持。在这种背景下,确保系统时刻处于最佳状态的重要性。而监控易的巡检管理功能&#…...
技能点总结
技能点总结 1、多线程导致事物失效的原因1.1 线程间竞争条件1.2 可见性问题1.3 原子性破坏1.4 死锁与活锁1.5 事务隔离级别问题1.5.1 脏读、不可重复读、幻读 1、多线程导致事物失效的原因 多线程环境下事物失效是一个常见问题,主要原因包括以下几个方面࿱…...
23种设计模式-行为型模式之命令模式(Java版本)
Java 命令模式(Command Pattern)详解 🧠 什么是命令模式? 命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使你可以使用不同的请求、队列、日志请求以及支持可撤销的操作。 命令模式将请求的…...
聊一聊接口测试的核心优势及价值
目录 一、核心优势 提前发现问题,降低修复成本 高稳定性与维护效率 全面覆盖复杂场景 性能与安全测试的基石 高度自动化与高效执行 支持微服务与分布式架构 二、核心价值 加速交付周期及降低维护成本 提升质量与用户体验 增强安全性及促进团队间的协作 …...
大学之大:索邦大学2025.4.27
索邦大学:千年学术传承与现代创新的交响 一、前身历史:从巴黎大学到现代索邦的千年脉络 1. 中世纪起源:欧洲学术之母的诞生 索邦大学的历史可追溯至9世纪,其前身巴黎大学被誉为“欧洲大学之母”。1257年,神学家罗伯特…...
python文本合并脚本
做数据集本地化时,用到了文本txt合并问题,用了trae -cn ai辅助测试一下效果,还可以吧,但还是不如人灵光,反复的小错,如果与对成手,应该很简单,这里只做了测试吧,南无阿弥…...
Coding Practice,48天强训(25)
Topic 1:笨小猴(质数判断的几种优化方式,容器使用的取舍) 笨小猴__牛客网 #include <bits/stdc.h> using namespace std;bool isPrime(int n) {if(n < 1) return false;if(n < 3) return true; // 2和3是质数if(n % 2 0 …...
pytorch学习使用
1. 基础使用 1.1 基础信息 # 输出 torch 版本 print(torch.__version__)# 判断 cuda 是否可用 print(torch.cuda.is_available()) """ 2.7.0 False """1.2 创建tensor # 创建一个5*3的矩阵,初始值为0. print("-------- empty…...
《AI大模型应知应会100篇》第38篇:大模型与知识图谱结合的应用模式
第38篇:大模型与知识图谱结合的应用模式 摘要 随着大模型(如GPT、BERT等)和知识图谱技术的快速发展,两者的融合为构建更精准、可解释的智能系统提供了新的可能性。本文将深入探讨大模型与知识图谱的能力互补性、融合架构设计以及…...
TypeScript中的type
在 TypeScript 中,type 是一个非常重要的关键字,用于定义类型别名(Type Alias)。它允许你为一个类型创建一个新的名字,从而使代码更加简洁和可读。type 可以用来定义基本类型、联合类型、元组类型、对象类型等。以下是…...
数据库3,
describe dt drop table 删表 df delete from删行 usw update set where更新元素 iiv insert into values()插入行 sf select from选行 select *选出所有行 (ob order by 排序 由低到高 DESC由高到低 order by score&#…...
I-CON: A Unifying Framework for Representation Learning
1,本文关键词 I-Con框架、表征学习、KL散度、无监督分类、对比学习、聚类、降维、信息几何、监督学习、自监督学习、统一框架 2,术语表 术语解释I-Con本文提出的统一表征学习方法,全称Information Contrastive Learning,通过最…...