数据结构与算法面试知识点汇总(超全)

article/2025/10/16 3:54:40

文章目录

  • 一、哈希函数和哈希表
    • 01 哈希函数
    • 02 哈希表
  • 二、布隆过滤器
  • 三、一致性哈希
  • 四、并查集
    • 01 具体实现
    • 02 优化
    • 03 代码实现
  • 五、前缀树(trie树)
  • 六、B树和B+树
  • 七、线段树
    • 01 线段树的优势
    • 02 线段树实现


一、哈希函数和哈希表

01 哈希函数

哈希函数(散列函数):类似于函数调用一样,给一个字符串作为输入,返回一个哈希码。
哈希表(散列表):把哈希码映射到表中的一个位置来访问记录,存放记录的数组就叫散列表

  • 直接寻址法:hash(key) = a * key + b
  • 数字分析法
  • 平方取中法
  • 折叠法
  • 随机数法
  • 除留余数法

性质:
1)输入域是无穷大的
2)输出域是有穷的,输出域要比输入域小
3)哈希函数不是一个随机函数,只要输入一样,输出就一样
4)输入域这么大而输出域这么小,而由于特性3的关系,就会导致输入不一样也有可能得到输出一样的值(哈希碰撞)
5)虽然有哈希碰撞,如果输入够多,将在整个输出域上均匀地出现返回值,不一定完全平分,但输出域中的每个哈希码一定被差不多个输入域中的值对应
6)因为要做到均匀分布,于是哈希函数跟输入的规律是没有关系的,可以打乱输入规律

推广:
当输入域足够大,经过一个哈希函数计算完后保证输出域是均匀分布时,
对输出域的每一个哈希码模%上一个m,最终的域会缩减成0至m-1,也均匀分布

工程应用:
如何找到1k个相对独立的哈希函数,一个哈希函数的规律跟另一个哈希函数的规律是无关的
只要用1个哈希函数就能改出1k个来,如:哈希f1 + k * 哈希f2 = 哈希fn

02 哈希表

实现原理:
在这里插入图片描述

解决哈希冲突(key1和key2称为同义词)的方法:

  • 开放寻址法(包括线性探测再散列、二次探测再散列(改善堆积现象)、伪随机探测再散列、双散列法),容易造成堆积现象
  • 链地址法:在原地址新建一个空间,以链表结点的形式插入到该空间。链地址算法的基本思想是将所有哈希地址为 i 的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。插入新数据项的时间随装载因子线性增长。

哈希表扩容:

如果发现某个位置上的链的长度到达k了,那么可以认为其它位置上链的长度也到达k了。此时,可能下一次加记录的话效率就不行了,这时就要经历哈希表的扩容

  • 首先要将原来的哈希域(如前面的17),扩展到104(或别的)。
  • 扩完之后如果要模104,则原来的记录都会失效。此时要将每一个记录都拿出来,用哈希函数计算完之后去模上104,再分配其在哪个位置。

那么,扩容代价不用计算吗?为什么能做到O(1)呢?
一方面样本量是N,若每次扩容都让哈希域长度增加k倍,则扩容平均代价是O(logkN)可很低
另一方面还可以离线扩容。
于是哈希表的增删改查是O(1)的。

Q:有一个大文件100T,每一行是一个字符串,是无序的,让你打印重复的字符串
A:如果单核单CPU单台机器去搞这个事情,那头都大了
Q:说得对,那你怎么办?
A:这是一个大数据问题,可以通过哈希来分流,你给我多少台机器呢?大文件存在哪呢?
Q:给你1000台机器干这个事情,大文件存在一个分布式文件系统上,按行读有很快的工具
A:

  • 1)首先对机器标号0-999,把每一行作为一个文本读出来,
    利用哈希函数去算一个哈希码,去模1000,
    当然也不一定要你提供的1k台机器,只要我能知道里面有m种字符串就好了,就模m
  • 2)然后将结果放到对应标号的机器中,用一个文件记录下来。
    这样就把这个大文件分到了m台机器上去,而且相同的重复文本一定会分配到同一台机器上(哈希函数的性质:相同输入相同输出,不同输入均匀分布)
  • 3)然后在单台机器上去统计有哪些重复的,最后就是1k台机器并发
    如果单台机器上的文件还是太大,再在这个机器上做相同的步骤,在单台机器上并行计算即可

二、布隆过滤器

主要用于解决爬虫去重问题以及黑名单问题,其短板是它有失误率。

这个失误是指:宁可错杀,绝不放过1个的类型。如果是坏人,一定报警。如果是好人,也可能报警,但几率较小

以黑名单问题来举例:

有这么个需求,100亿个URL是黑名单,假设每个URL是64字节,
当用户想搜索某个URL时,如果它是黑名单里的URL,就要对它进行过滤

解决方案:
1)首先它可以通过哈希表实现,但是需要多少个空间呢?

  • 由于这里面不用存value,只用存key,于是它是一个hashSet,key是URL字符串
  • 这里起码需要6400亿个字节才能把这些URL装下,还不算指针、索引等所占的空间,实际上是比6400亿字节(640G)大的, 如果做成哈希表全放内存中,代价是很高的,而且服务器还要用分布式内存
  • 这个设计就耗费了巨大的代价。即便用哈希函数分流到多个机器上,这浪费了机器

2)那怎么能仅适用一台机器就能提供服务呢?——布隆过滤器

  • 在哈希来哈希去的经典方法说了以后,应该问允许有很低的失误率吗?——允许。这个时候就可以使用布隆过滤器。它是一个bit类型的map。

实现方法:
第一步:
准备一个数组,从0到m-1位置,每个位置上不是整数也不是串,是一个bit,只有两种状态0/1
int *arr = new int[1000]; // 分配4*1000字节的连续内存,共4*1000*8个bit
在这里插入图片描述
这样,就用基础类型int做出了一个0到m-1长度为m的bit类型的数组。如果想省空间,就用long类型,8个字节64位。此外还能做成矩阵的形式。
如果想让第300000个bit位置置1,此时int index = 300000,

  • ① 定位这个bit来自于哪个桶 int intIndex = index / 32;
  • ② 定位这个位置来自于这个桶的哪个bit位 int bitIndex = index % 32;
  • arr[intIndex] = (arr[intIndex] | (1 << bitIndex));

第二步:
有了这个数组以后,

  • ① 将黑名单内的所有URL,输入k个相互独立的哈希函数中得到k个哈希码分别取模上m,算出来的对应数组中的那个位置1。若产生哈希碰撞,不管,还是置1。这个过程结束以后,URL进入布隆过滤器。注意:这个数组应当长一些,如果太短,则很容易每个位置都变成1,这样用户输入的URL就全都是黑名单了。
  • ② 查URL的过程:将用户提供的URL,也做步骤①,如果算出来的k个位置都已经置1,则说这个URL在黑名单中。如果仅有一个甚至几个没被置1,说明这个URL不在黑名单中(哈希函数特性:相同输入一定有相同输出)。失误的时候就出现在数组开的比较小。
  • 通过调整数组的大小m和哈希函数的个数k,可以得到不同的失误率。
    在这里插入图片描述

三、一致性哈希

经典服务器抗压结构:
比如提供一个根据用户QQ号(key)返回其网龄(value)的服务。如何使其负载均衡呢?

  • 首先会有一个前端(Nginx),用于接受请求,请求可以发送到任意一个前端上,提供的服务相同
  • 然后有一个后端集群组,假设有3台机器m1,m2,m3
  • 首先信息会发送到前端上,经前端的同样一份哈希函数算出哈希码,模上3得到对应的机器,将这个信息存到对应的机器中。如果数据足够多,数据是均匀地存在三台机器中的,负载均衡:每台机器处理的东西是差不多的,CPU占用差不多,内存使用差不多,相关系统性能指标差不多。
  • 在查的时候,依然是经过上面的步骤,由于相同输入一定导致相同输出,就会到相应的机器上去拿出这个记录,返回给前端,然后前端返回给用户。

上面提到的经典服务器有什么问题呢?——当增加机器或减少机器时,它就炸了

原因:
这和哈希表扩容是一样的,如果加机器加到100,原来模的是3,现在要模100,所有的数据归属全变了。所以必须要把原来的记录都拿出来再算一次,然后迁移到相应的机器上。代价很高

于是有了一致性哈希结构,可实现把原来全部数据迁移的代价变得很低,并负载均衡

具体是这样的:
在这里插入图片描述
那么如何实现它呢?

  • 对于后端——还是那三台机器
  • 对于前端——还是无差别的负载的服务器

然后,对三台机器对应的哈希值排好序之后做成一个数组存到前端中去
这样,不管请求发送到前端的哪一个机器上,由于每个机器上都有这么一个数组,二分的方式找到第一个大于等于算出来的哈希值的那个位置,就知道这个请求应当由哪个机器处理了。
即便你有10亿台机器,由于采用二分的方法,log以后复杂度也是很低的。

那为什么说它克服了传统服务器结构中加减机器的问题呢?

比如加了一台m4,同样也映射到环上。
在这里插入图片描述
这样,

  • 在增加机器时,不需要去迁移m1和m3全部的数据,只用迁移原本属于m2的数据即可完成
  • 在减少机器时,只需要把m4的数据迁移到m3上即可

于是,这种结构,加减机器数据迁移的代价是非常低的

但是,存在什么问题呢

  1. 在机器数量比较少时,这个环是不能够保证其均分的(哈希函数的性质:量在多的时候,才是均匀分布的)。这样负载就会出现问题,一台机器很忙,一台机器却闲得发慌
  2. 即便可以保证均匀,在加一个机器之后负载就不均了

把上述两个问题解决了,一致性哈希就能既做到数据迁移的代价小,又能保证负载均衡

虚拟结点技术:

  • 真实机器m1,给它分配1k个虚拟结点
  • m2,m3也同样都分配1k个虚拟结点

此时,不让m1,m2,m3各自的ip去映射到环上,

  • 准备一张路由表,这个路由表可以由真实机器去查它有哪些虚拟结点,同样也可以由虚拟结点去查它属于哪个真实机器
  • 让这3k个虚拟结点经哈希函数映射到环上,某个虚拟结点负责的域均给它的真实机器处理
    3k个虚拟结点占据了这个环,于是三台机器负责的数据就是差不多的了,负载均衡!

如果此时增加一台机器m4,让它也分配1k个虚拟结点,让它们直接进环,再做数据迁移即可
拿走的数据(由m1、m2、m3的部分数据组成)是由虚拟结点决定的

虚拟结点导致的哈希冲突:冲冲呗,碰撞的概率很小,两个机器共同存一份。


四、并查集

解决的是

  • 1)非常快地检查两个元素各自所在的集合是否属于一个集合。
  • 2)两个元素各自所在的集合,合并在一块

例子:有元素A,元素B,其中A∈集合set1,B∈集合set2

  • 对于1),有函数isSameSet(A, B),用于查set1和set2是否一个集合。
  • 对于2),有函数union(A, B),用于set1和set2合并。

那么可以怎么实现呢?

  • 方案1:
    使用链表list,把每个集合当做一个list,每个元素是一个node,放在list中
    对isSameSet而言,可以遍历list1,看其中有没有B(缺点是需要遍历,慢
    对union而言,就把两个list接起来即可
  • 方案2:
    使用哈希表set,把每个集合当做一个set,每个元素是一个node,放在set中
    对isSameSet而言,可以再set1中以O(1)去查有没有B。
    对union而言,要把set2所有的东西都扔到A中(缺点是也需要遍历

初始化:
初始化时必须一次性把所有的数据样本给它,不能动态地过来(如

01 具体实现

代表结点代表整个集合在这里插入图片描述

  • 对于isSameSet,只需要通过元素A和元素B不断往上找直到找到各自代表结点,查它们的代表结点是否相同就可以判断它们是否在桶一个集合中。
  • 对于union,首先要通过元素A和元素B不断往上找直到找到各自代表结点,让数量少的那个set挂在数量多的那个set上。合并set的代表结点是原来数量多的那个set的代表结点。

02 优化

看出每一次查询操作的时间复杂度为O(H),H为树的高度
于是只要去查某个元素的代表结点时,都涉及下面的优化

在这里插入图片描述

03 代码实现

class UnionSet {unordered_map<int, int> fatherMap;  // child - fatherunordered_map<int, int> sizeMap;    // node - sizeOFset
public:UnionSet(int n) {for (int i = 1; i <= n; ++i) {fatherMap[i] = i;sizeMap[i] = 1;}}int findRoot(int node) {if (fatherMap[node] == node)return node;return findRoot(fatherMap[node]);}void Union(int node1, int node2) {int root1 = findRoot(node1);int root2 = findRoot(node2);if (root1 == root2)return;if (sizeMap[root1] <= sizeMap[root2]) {fatherMap[root1] = root2;    sizeMap[root2] += sizeMap[root1];    sizeMap.erase(root1);} else {fatherMap[root2] = root1;sizeMap[root1] += sizeMap[root2];   sizeMap.erase(root2);}}int getSize() {return sizeMap.size();}bool isInSameSet(int node1, int node2) {return findRoot(node1) == findRoot(node2);}
};

刷题笔记32——STL::map实现并查集、岛问题


五、前缀树(trie树)

效率很高:

  • 每个节点保存一个字符
  • 根节点不保存字符
  • 每个节点最多有n个子节点(n是所有可能出现字符的个数)
  • 查询的复杂度为O(k),k为查询字符串长度

功能举例:
在这里插入图片描述

六、B树和B+树

B树和B+树的出现是因为一个问题——磁盘IO。所以在大量数据存储中,查询时不能一下将所有数据加载到内存中,只能逐一加载磁盘页,每个磁盘页对应树的结点。造成大量磁盘IO操作(最坏情况下为树的高度)。

  • 所以,这里将树变得矮胖来减少磁盘IO的次数——采用多叉树,每个结点存储多个元素,又根据AVL得到一棵平衡多路查找树可以使得数据查找效率在O(logN)

B树:

  • 每个节点都存储key和value,所有的节点组成这棵树,并且叶子结点指针为null
  • 一个m阶B树最多有m个孩子,若根结点不是叶子结点,则至少有 2 个孩子
  • 所有叶子结点都在一层
  • 先由根结点找磁盘块1,读入内存(IO第一次);
  • 比较,找指针p2;
  • 根据p2指针找到磁盘块3,读入内存(IO第二次),在磁盘块3中的关键字列表中找到关键字30

综上,需2次磁盘IO操作,2次内存查找操作;由于内存在红的关键字是一个有序表结构,可以用二分法提高效率
故 3 次磁盘IO操作是影响整个B树查找效率的决定因素,它相对于AVL树缩减了结点的个数
在这里插入图片描述

B+树非叶子节点只存储key,只有叶子结点存储value,叶子结点包含了这棵树的所有键值,每个叶子结点有一个指向相邻叶子结点的指针,这样可以降低B树的高度
在这里插入图片描述
为什么B+树是数据库实现索引的首选数据结构呢?——评价一个数据结构作为索引的指标就是在查找时IO操作的次数

1、这棵树比较矮胖,树的高度越小,IO次数越少
2、一般来说,索引很大,往往以文件的形式存储在磁盘上,索引查找时产生磁盘IO消耗,相对于内存读取,IO存取的消耗比较高

聚集索引:data存数据本身,索引也是数据。数据和索引存在一个文件中。
非聚集索引:data存的是数据地址,索引是索引,数据是数据

根据B+树的结构,我们可以发现B+树相比于B树,在文件系统,数据库系统当中,更有优势,原因如下:

  1. B+树单一节点存储更多的元素,使得查询的IO次数更少
    B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说I/O读写次数也就降低了。

  2. B+树所有查询都要查找到叶子节点,查询效率更加稳定
    由于内部结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

  3. B+树所有叶子节点形成有序链表,便于范围查询,更有利于对数据库的扫描
    B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题,而B+树只需要遍历叶子节点就可以解决对全部关键字信息的扫描,所以对于数据库中频繁使用的range query,B+树有着更高的性能

七、线段树

来源

对一个很大的一维数组 arr,对里面的数字我们要反复做两个操作:

  • query(arr, L, R) :随机选一个区间 [L, R],要把区间内的数都加起来 —— O(n)
  • update(arr, i, val):随机修改数组中的一个值 —— O(1)

那么,现在要做这两个操作,由于 query 是 O(n) 的,那么就整个过程就非常慢,有什么办法把 query 操作变成 O(1) 的吗?

  • 创建一个同样大小的 sum_arr 数组,前 n 项和放到 sum_arr 对应的位置上
  • 于是,sum = a - b,这样 query 的复杂度就变为 O(1),而 update 就变成 O(n) 了
    在这里插入图片描述

更好的办法是使用 —— 线段树,把这两个操作的复杂度都变为 O(logn)

01 线段树的优势

  • 1)根结点表示数组元素的总和

  • 2)分叉,把数组劈成两半。做法就是不断二分,最终所有的叶子结点就是数组中的元素
    在这里插入图片描述

  • 3)填每一个结点
    在这里插入图片描述

  • 4)有一个 query 需求,要算区间 [2, 5] 以内的和。那么我们就把这个区间分半,分成 [2] 和 [3, 5]。这样,对query,最坏情况就是把这棵树从根结点到叶子结点搜索一遍,复杂度变为了 O(logn)。
    在这里插入图片描述

  • 5)有另一个需求 update,要把 4 位置上的数字改为 6,那么我们就先顺着这条路找到 4 位置,然后再返回去修改这条路上的和,其他路径不会受到影响。所以总的时间复杂度也是 O(logn) 的
    在这里插入图片描述

02 线段树实现

1)构建线段树

  • 做一棵满二叉树,没有结点的地方填充虚节点。这样,根据堆结构的原理,我们能很容易求出当前结点的左右孩子。
  • PS:线段树一般开 4倍arrSize 的大小
    在这里插入图片描述

2)线段树的更新

  • 从根结点开始,确定要改左分支还是右分支,找叶子结点并修改(注意 arrTmp 和 tree 数组对应的位置都要改)
  • 更新之后,往上改区间和

3)线段树的查询

  • 同样我们要去查询左边和右边,左边和右边的结果加起来就是我们要找的区间和
  • 这个结果什么时候返回呢?换句话说,我们如何知道找到了这个结果从而结束递归呢?
  • 如果不在计算范围内,返回0。也就是说,如果我们的 [L, R] = [4, 5],而 [start, end] = [0, 2],就会出现在 arr 的 [0, 2] 中去找 [4, 5],这两段区间没有重合的部分,所以直接返回 0。不在计算范围内的情况如下图所示,所以条件是 R< start || end < L
    在这里插入图片描述
  • 如果正好计算到叶节点,那么就返回叶节点上的数字。条件是 start == end,但这里的问题是,必须要递归到叶子结点,而实际上,比如我们要求 [2, 5] 区间内的和,当我们找到 [3,5] 这个区间和的时候,递归就可以结束了,不需要再往下递归到叶子结点。所以,这个条件应该改为 L <= start && end <= R
class SegTree {vector<int> tree;vector<int> arrTmp;void buildTreeCore(const vector<int>& arr, int curNode, int start, int end) {if (start == end)tree[curNode] = arr[start];else {int mid = start + ((end - start) >> 1);int leftChild = 2 * curNode + 1;int rightChild = 2 * curNode + 2;buildTreeCore(arr, leftChild, start, mid);buildTreeCore(arr, rightChild, mid + 1, end);tree[curNode] = tree[leftChild] + tree[rightChild];}}void updateTreeCore(int curNode, int start, int end, int idx, int val) {if (start == end) {arrTmp[idx] = val;tree[curNode] = val;} else {int mid = start + ((end - start) >> 1);int leftChild = 2 * curNode + 1;int rightChild = 2 * curNode + 2;if (idx >= start && idx <= mid)updateTreeCore(leftChild, start, mid, idx, val);elseupdateTreeCore(rightChild, mid + 1, end, idx, val);tree[curNode] = tree[leftChild] + tree[rightChild];}}int queryTreeCore(int curNode, int start, int end, int L, int R) {if (R < start || end < L)return 0;else if (L <= start && end <= R)return tree[curNode];else {int mid = start + ((end - start) >> 1);int leftChild = 2 * curNode + 1;int rightChild = 2 * curNode + 2;int sumOfLeft = queryTreeCore(leftChild, start, mid, L, R);int sumOfRight = queryTreeCore(rightChild, mid + 1, end, L, R);return sumOfLeft + sumOfRight;}}
public:void buildTree(const vector<int>& arr) {if (arr.empty())return;arrTmp = arr;int sz = arr.size();tree = vector<int>(4 * sz, 0);		// 线段树一般开4倍大小buildTreeCore(arr, 0, 0, sz - 1);}void updateTree(int i, int val) {updateTreeCore(0, 0, arrTmp.size() - 1, i, val);}int queryTree(int L, int R) {return queryTreeCore(0, 0, arrTmp.size() - 1, L, R);}
};

http://chatgpt.dhexx.cn/article/6ErxmHs0.shtml

相关文章

《数据结构》十道链表经典面试题多种方法深度解析

目录 ⛰️一、题目解析 &#x1f5fb;1.1删除链表中等于给定值 val 的所有节点&#xff08;力扣&#xff09; &#x1f5fb;1.2反转一个单链表。&#xff08;力扣&#xff09; &#x1f5fb;1.3给定一个带有头结点 head 的非空单链表&#xff0c;返回链表的中间结点。如果有…

数据结构和算法常见面试问题总结,含答案

0. 写在前面 总导航在此 这些问题是我备考数据结构和算法的过程中&#xff0c;详细总结的常见面试问题和答案。逐个搜索并记录下来&#xff0c;花了很大的精力&#xff01;如果想要获取源文件的话&#xff0c;可以关注我的微信公众号&#xff1a;小梁说代码&#xff0c;获取嘿…

(六)数据结构面试必问

什么是链表、队列、栈&#xff1f; 链表&#xff1a; 当需要存储多个相同数据类型的时候&#xff0c;可以使用数组存储&#xff0c;数组可以通过下标直接访问&#xff0c;但数组有个缺点就是无法动态的插入或删除其中的元素&#xff08;特别是操作第一个位置上的元素&#xff…

数据结构常见面试题

链表是最基本的数据结构&#xff0c;面试官也常常用链表来考察面试者的基本能力&#xff0c;而且链表相关的操作相对而言比较简单&#xff0c;也适合考察写代码的能力。链表的操作也离不开指针&#xff0c;指针又很容易导致出错。综合多方面的原因&#xff0c;链表题目在面试中…

面试中常见的数据结构

上次在面试时被面试官问到学了哪些数据结构&#xff0c;那时简单答了栈、队列/(ㄒoㄒ)/~~其它就都想不起来了&#xff0c;今天有空整理了一下几种常见的数据结构&#xff0c;原来我们学过的数据结构有这么多~ 首先&#xff0c;先来回顾下C语言中常见的基本数据类型吧O(∩_∩)O …

数据结构算法常见面试考题

&#xff08;1&#xff09; 红黑树的了解&#xff08;平衡树&#xff0c;二叉搜索树&#xff09;&#xff0c;使用场景 把数据结构上几种树集中的讨论一下&#xff1a; 1.AVLtree 定义&#xff1a;最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为…

八大数据结构及常见面试题

几乎所有的问题都需要面试者对数据结构有深刻的理解。无论你是初入职场的新兵(刚从大学或者编程培训班毕业)&#xff0c;还是拥有几十年经验的职场老鸟。 即便是对于一些非常基础的工作来说&#xff0c;学习数据结构也是必须的。那么&#xff0c;就让我们先从一些基本概念开始入…

数据结构面试、数据结构考研复试——常见问题以及回答

说明&#xff1a;这些是自己整理回答的答案 可以借鉴 也可能存在错误 欢迎指正 文章目录 逻辑结构与物理结构的区别算法常见的数据结构链表存储结构和顺序存储结构的区别数组和链表的区别头指针和头结点的区别线性链表判断整个链表是否有环&#xff0c;如何找到这个环单链表和…

架构设计分布式数据结构与算法面试题(2020最新版)

Java面试总结&#xff08;2021优化版&#xff09;已发布在个人微信公众号【技术人成长之路】&#xff0c;优化版首先修正了读者反馈的部分答案存在的错误&#xff0c;同时根据最新面试总结&#xff0c;删除了低频问题&#xff0c;添加了一些常见面试题&#xff0c;对文章进行了…

数据结构面试题以及答案整理

参考网络整理的一些问题 一、什么是数据结构&#xff1f; 数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。结构包括逻辑结构和物理结构。 数据的逻辑结构包括4种 (1)集合&#xff1a;数据元素之间除了有相同的数据类…

数据结构面试常见问题总结

数据结构面试常见问题总结 写在前面 本文记录了一些数据结构面试常见问题&#xff0c;本意用于考研复试&#xff0c;以下面试题为网上整理的问题以及自己加入的一些问题&#xff0c;答案仅供参考&#xff01; Q&#xff1a;数据结构三要素 A&#xff1a;逻辑结构、物理结构、…

mysql 驱动包 mysql-connect-java

mysql的驱动包 mysql-connect-java 内部封装了jdbc: jdbc(java database connectivity):本身是由一组接口组成 , 可以使得Java编译来访问各种数据库无需自己实现接口,这些接口的实现类由第三方数据库厂商实现 jdbc的核心 接口或类作用DriverManager类创建数据库的连接Conne…

Mysql 驱动包mysql-connector-java-8.0.25.jar下载

安装地址 https://downloads.mysql.com/archives/c-net/ 按需选择所需版本&#xff0c;点击Download即可下载&#xff1b; 网盘下载地址&#xff1a; 需要的小伙伴&#xff0c;请关注微信公众号: Transkai, 或者扫描下方公众号二维码&#xff0c;回复关键字&#xff1a;mysql驱…

下载MySQL驱动程序

下载步骤&#xff1a; 第一步&#xff1a;进入MySQL官方网站&#xff0c;并选择DOWNLOADS和Community。 第二步&#xff1a;选择MySQL Connectors 第三步&#xff1a;选择Connector/J 第四步&#xff1a;进入下面界面&#xff0c;找到下面的Generally available (GA)…

【java】Java连接mysql数据库及mysql驱动jar包下载和使用

文章目录 JDBCJDBC本质&#xff1a;JDBC作用&#xff1a;跟数据库建立连接发送 SQL 语句返回处理结果 操作流程和具体的连接步骤如下&#xff1a;操作步骤&#xff1a;需要导入驱动jar包 mysql-connector-java-8.0.22.jar注册驱动获取数据库连接对象 Connection定义sql获取执行…

Mysql-connector-java驱动包(最新版下载详细教程)

步骤如下&#xff1a; 1.进入下载官网 https://dev.mysql.com/downloads/ 2.点击Connector/J 3.选platform Independent选项 4.选zip 5.选择不登陆进行下载 6.自己选择下载到哪个文件夹即可下载成功

Java连接MySQL mysql-connector-java-bin.jar驱动包的下载与安装

eclipse在连接mysql数据库的时候要通过mysql驱动包进行连接 首先进入官网中----官网地址&#xff1a;https://dev.mysql.com/ 进入官网中选择DOWNLOADS&#xff08;下载&#xff09; 2. 选择下载中的mysql-connectors 3. 选择connector/J J指的是Java 4.接下在选择操作系统…

Java连接mysql数据库及mysql驱动jar包下载和使用(详细记录)

JDBC 基本概念&#xff1a;java 数据库连接&#xff0c;简称&#xff1a;&#xff08; java DataBase Connectivity &#xff09;&#xff0c;java语言操作数据库。 JDBC本质&#xff1a; 其实是官方&#xff08;SUN公司&#xff09;定义的一套操作所有关系型数据库的规则&…

记录下载com.mysql.jdbc.Driver驱动包过程

一、网上找了好多要么收费要么没有资源&#xff0c;所以只好去官网上找了 二、官网地址 https://dev.mysql.com/downloads/ 三、下载过程 1、点击官网进去点击downloads 2、点击MySQL Community (GPL) Downloads 进去 3、点击MySQL Community Downloads下的Connector/J 4、在这…

1.MySql驱动的jar包下载

文章目录 1.下载MySql驱动的jar包 1.下载MySql驱动的jar包 1&#xff09;官网&#xff1a;http://dev.mysql.com/downloads/connector/ 2&#xff09;点击右边的Connetor/J 3&#xff09;点击Archives 4&#xff09;Product Version为MySql驱动版本&#xff0c;可以根据需要…