![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
数据结构
文章平均质量分 76
thetffs
这个作者很懒,什么都没留下…
展开
-
数据结构与算法之美_26_红黑树
什么是红黑树 一颗红黑树需要同时满足以下4个条件: 定义1:根节点是黑色的; 定义2:每个叶子节点都是黑色的空节点(NIL),也就是说,叶子节点不存储数据; 定义3:任何相邻的节点都不能同时为红色,也就是说,红色节点是被黑色节点隔开的; 定义:4:每个节点,从该节点到达其可达叶子节点的所有路径,都包含相同数目的黑色节点; 如何实现一个红黑树 1、插入操作 红黑树规定,插入的节点必须是红色的。而且,二叉查找树中新插入的节点都是放在叶子节点上。 ①如果插入节点的父节点是黑色的,那我们什么都不用做,它仍然满足红黑原创 2020-12-10 21:50:30 · 57 阅读 · 0 评论 -
数据结构和算法之美_25_红黑树
带着问题去学习 为什么工程中都喜欢使用红黑树这种二叉树 AVL 树是一种高度平衡的二叉树,所以查找的效率非常高,但是,有利就有弊,AVL 树为了维持这种高度的平衡,就要付出更多的代价。每次插入、删除都要做调整,就比较复杂、耗时。所以,对于有频繁的插入、删除操作的数据集合,使用 AVL 树的代价就有点高了。红黑树只是做到了近似平衡,并不是严格的平衡,所以在维护平衡的成本上,要比 AVL 树要低。所以,红黑树的插入、删除、查找各种操作性能都比较稳定。对于工程应用来说,要面对各种异常情况,为了支撑这种工业级的应用原创 2020-12-22 15:03:15 · 80 阅读 · 0 评论 -
数据结构和算法之美_24_二叉查找树
二叉查找树(Binary Search Tree) 二叉查找树要求,在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值。二叉查找树支持快速的查找、插入、删除操作。 需要掌握的二叉查找树的操作 查找、插入、删除、查找最大结点、查找最小结点、查找前驱结点、查找后继结点、中序遍历二叉查找树输出有序序列 二叉查找树的操作–查找 我们先取根节点,如果它等于我们要查找的数据,那就返回。如果要查找的数据比根节点的值小,那就在左子树中递归查找;如果要查找的数据比根节点的原创 2020-12-22 15:03:36 · 75 阅读 · 0 评论 -
数据结构和算法之美_23_二叉树
带着问题去学习: 1、二叉树有哪几种存储形式?什么样的二叉树适合用数组去存储? 树(Tree) 比如下面这幅图,A 节点就是 B 节点的父节点,B 节点是 A 节点的子节点。B、C、D 这三个节点的父节点是同一个节点,所以它们之间互称为兄弟节点。我们把没有父节点的节点叫做根节点,也就是图中的节点 E。我们把没有子节点的节点叫做叶子节点或者叶节点,比如图中的 G、H、I、J、K、L 都是叶子节点。 关于“树”,还有三个比较相似的概念:高度(Height)、深度(Depth)、层(Level)。 二叉树(原创 2020-12-13 18:33:02 · 169 阅读 · 1 评论 -
数据结构和算法之美_21_哈希算法
什么是哈希算法? 将任意长度的二进制串映射为固定长度的二进制串的方法就叫哈希算法。通过原始数据映射后得到的二进制串就叫哈希值。 哈希算法需要满足什么要求? 1、从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法); 2、对输入数据非常敏感,哪怕原始数据只修改了一个 Bit,最后得到的哈希值也大不相同; 3、散列冲突的概率要很小,对于不同的原始数据,哈希值相同的概率非常小; 4、哈希算法的执行效率要尽量高效,针对较长的文本,也能快速地计算出哈希值。 实际开发中如何使用哈希算法解决问题 1、业界常用的原创 2020-12-22 14:58:31 · 211 阅读 · 0 评论 -
数据结构和算法之美_18_散列表
散列表 散列表是一种基于数组按下标随机访问特性的数据结构。因此说散列表是数组的扩展,是由数组演变而来。 散列思想 用散列表存储数据使用的是散列思想。我们把需要存储到数组里面的元素称为键(key)或者关键字。把映射元素和存储位置的方法称为哈希函数,将哈希函数计算的值称为哈希值(散列值)。哈希值即映射后的数组下标。散列思想即将通过哈希函数建立关键字和其存储下标的映射关系。 散列冲突 散列冲突指不同关键字经过哈希函数后计算的哈希值相同: key1 ≠ key2,但是hash(key1) = hash(key2)原创 2020-12-22 15:09:59 · 87 阅读 · 2 评论 -
数据结构和算法之美_19_散列表
设计一个工业级应用的散列表 如何设计散列表 如何设计一个散列表能够在散列冲突的情况下应对散列表性能急剧下降,并且能够抵抗散列碰撞攻击 1、散列函数的设计不能太复杂,散列函数生成的值要尽可能随机并且均匀分布 2、考虑关键字的长度 特点 分布还有散列表的大小 装载因子过大怎么办? 装载因子 = 散列表存放的元素个数/散列表大小 装载因子过大说明散列表中元素越多,空闲位置越少,当装载因子大到一定程度的时候散列冲突就变得不可接受,我们可以进行动态扩容。动态扩容导致散列表的 如何实现word拼写检查功能 ...原创 2020-12-22 15:10:14 · 93 阅读 · 1 评论 -
数据结构与算法之美_16_二分查找变形
四个需要掌握的二分查找变形问题 变体一:查找第一个值等于给定值的元素 public int bsearch(int[] a, int n, int value) { int low = 0; int high = n - 1; while (low <= high) { int mid = low + ((high - low) >> 1); if (a[mid] > value) { high = mid - 1; } else原创 2020-12-22 15:10:37 · 112 阅读 · 0 评论 -
数据结构与算法之美_15_二分查找
二分查找 什么是二分查找? 二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。 二分查找的查找速度为 O(logn) 区间大小为n的一组数据,查找次数至多为k次,此时n/(2^k) = 1,因此时间复杂度为O(logn)。 二分查找的非递归实现 int binary_search(int a[], int n , int value) { int low = 0; int high = n - 1; wh原创 2020-12-22 15:11:01 · 154 阅读 · 0 评论 -
数据结构与算法之美_14_排序优化
编程语言提供的排序算法 c语言:qsort()函数 C++的STL:sort() , stable_sort()函数 JAVA:Collections.sort() 如何选择合适的排序算法 实际应用中我们选用时间复杂度为O(nlogn)的排序算法 1、从实际应用场景考虑 线性排序算法的时间复杂度比较低,适用场景比较特殊。所以如果要写一个通用的排序函数,不能选择线性排序算法。 2、从数据规模考虑 小数据规模选用时间复杂度为O(n^2)的排序算法,大数据规模选用时间复杂度为O(nlogn)的排序算法。所以,为原创 2020-12-22 15:12:26 · 110 阅读 · 0 评论 -
数据结构和算法之美_13_排序
线性排序 时间复杂度为O(n)的排序算法称为线性排序,常见的线性排序包括桶排序、计数排序、基数排序。 桶排序(Bucket sort) 核心思想是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。 桶排序对排序数据的要求非常苛刻 首先,要排序的数据需要很容易就能划分成 m 个桶,并且,桶与桶之间有着天然的大小顺序。这样每个桶内的数据都排序完之后,桶与桶之间的数据不需要再进行排序。其次,数据在各个桶之间的分布是比较均匀的原创 2020-12-22 15:12:46 · 80 阅读 · 0 评论 -
数据结构和算法之美_12_归并排序、快速排序
归并排序(merge sort) 一、什么是归并排序? 使用归并排序对一组数据排序,首先将数据分为两个部分,再对两部分数据重新排序,最后将排序后的两部分数据合并成一组数据并使它有序。 归并排序算法采用了分治思想,分治就是将一个大问题分解成各个小的子问题来解决,和用递归解决问题的思路很像,事实上使用分治思想解决问题也需要用到递归的编程技巧。 void * merge(int a[], int p, int q, int r) { int *tmp; int i, j, k; tmp = (int *)原创 2020-12-11 13:05:49 · 118 阅读 · 1 评论 -
数据结构与算法之美_11_排序
需要掌握的8个排序算法 冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。 学习排序算法需要掌握什么? 1、算法思想 2、代码实现 3、算法执行效率 思考 插入排序和冒泡排序的时间复杂度相同,都是 O(n2),在实际的软件开发里,为什么我们更倾向于使用插入排序算法而不是冒泡排序算法呢? 冒泡排序 对一组数据进行排序,一次冒泡是依次比较相邻的两个数据,若满足顺序要求则不对元素进行交换,若不满足排序要求,怎交换元素位置。 1、具有n个元素的一组数据,最多需要进行n次冒泡 2、每次冒原创 2020-12-22 15:13:07 · 97 阅读 · 0 评论 -
数据结构和算法之美_10_递归
1、什么是递归? 一种非常高效、简洁的编码技巧,一种应用非常广泛的算法,比如DFS深度优先搜索、前中后序二叉树遍历等都是使用递归。基本上,所有的递归问题都可以用递推公式来表示。 2、为什么要用递归,它有哪些优缺点? 优点:递归代码虽然简洁高效 缺点:比如,堆栈溢出、重复计算、函数调用耗时多、空间复杂度高 3、 如何写出递归代码 ...原创 2020-12-10 21:36:23 · 50 阅读 · 0 评论 -
数据结构和算法之美_09_队列
队列(queue) 来历 特点 先进者先出,这就是典型的“队列” PS:无论顺序队列还是链式队列,队首指针指向队列中第一个元素,队尾指针指向队列的最后一个元素的下一个位置。入队时,现将元素入队,再将队尾指针后移一位。 适合解决的问题 实际的应用场景 作为一种非常基础的数据结构,队列的应用也非常广泛,特别是一些具有某些额外特性的队列,比如循环队列、阻塞队列、并发队列。它们在很多偏底层系统、框架、中间件的开发中,起着关键性的作用。比如高性能队列 Disruptor、Linux 环形缓存,都用到了循环并发队列。原创 2020-12-10 21:12:44 · 132 阅读 · 0 评论 -
数据结构和算法之美_08_栈
栈 来历 事实上栈是一种“操作受限”的线性表,只允许在数据的一端插入和删除。但是,我们需要理解的是特定的数据结构适用于特定的应用场景,数组和链表暴露了太多借口,操作起来容易出错,因此需要栈。 特点 先进后出,后进先出。 适合解决的问题 当某个数据集合只涉及在一端的插入和删除操作,且满足后进先出,先进后出的特性,我们就应该首先考虑选用“栈”这种数据结构。 实际的应用场景 浏览器的前进后退功能 问题描述:当你依次访问完一串页面 a-b-c 之后,点击浏览器的后退按钮,就可以查看之前浏览过的页面 b 和 a。当你原创 2020-12-10 21:09:03 · 121 阅读 · 1 评论