数据结构
文章平均质量分 62
路漫漫`
这个作者很懒,什么都没留下…
展开
-
分析为什么ArrayList、HashSet以及HashMap是线程不安全的
学习的时候都知道这三个是线程不安全的,但为什么是线程不安全的、具体在哪里不安全了却不太了解,这篇文章尝试分析一下。ArrayList它不安全的情况主要有这么几种(前提是多线程环境下):add元素之后,会出现有些位置的值为null的情况数组下标越界size大小不是预期的值下面分别对上述现象做出解释。出现null的情况先来看一下add方法的源码:private void add(E e, Object[] elementData, int s) { if (s == element原创 2021-09-15 13:17:04 · 608 阅读 · 0 评论 -
设计模式之装饰器模式
假设你有若干辆车,还有若干型号的配件,每个车都可以和某种配件组装,因此每种组合的价钱也不同。例如,有车A、B和C,配件有W1、W2和W3,那么,A和W1是一种组合,B和W1、W2也是一种组合,即车可以和一种或多种且数量不限的配件组合。应该如何设计呢?方案1 容易想到的方法先弄一个抽象类Car,所有的类都继承Car。如果只买车不买配件,那就是上图中的方框A,如果要计算价钱的话,直接让A实现Car中的computeCost方法就好了;如果想买车A和配件W1的话,就新建一个类,然后实现computeCo原创 2021-08-20 19:24:21 · 150 阅读 · 0 评论 -
几种最长XX类型的动态规划题目
无重复最长子数组遍历数组,每到一个新的位置i就看这个数字在之前是否出现过,如果没出现过直接dp[i] = dp[i-1] + 1,如果出现过,就看看i和之前出现过的位置的距离d是否比dp[i-1]大,要是大依然dp[i] = dp[i-1] + 1,(如 ayxyza,第二个a出现的位置下标是5,第一个a下标是0,相减等于5,而dp[4]=3,所以可以把这个a算进来);但如果d比dp[i-1]小,那么dp[i]就只能是d了(如abcb,b第一次是1,第二次是3,d=3-1=2,而dp[2]=3,所以dp[原创 2021-07-08 15:46:42 · 174 阅读 · 1 评论 -
leetcode147-链表排序(使用插入排序)
插入排序就是,初始时第一个数肯定是有序的,然后看第二个数,如果比第一个数小,那么就将第一个元素后移到第二个位置,然后将原第二个位置的元素插入到第一个位置;接着看第三个数…以1 3 2为例,初始时1自己肯定有序,然后看第二个元素3,比1大,所以继续看第三个元素2,它比3小,但比1大,因此将3右移到3位置,然后2插入到第二个位置:1 2 3.public ListNode sortInList(ListNode head) { // write code here if (head == n原创 2021-07-06 14:47:42 · 71 阅读 · 0 评论 -
最小生成树之克鲁斯卡尔(Kruskal)算法及其实现
这里就简单说一下步骤:先在所有边中选一条权值最小的检查这条边和结果集中的边是否构成了环,如果构成环,则回到第一步重新选择除这条边外权值最小的边;如果不构成环,那么将这条边加到结果集中重复上述过程直到所有的点都出现在结果集中用一个例子来理解:上图计算最小生成图的步骤如下:先选AC,AC并没有与结果集中的其他边(此时为空)构成环,因此将AC放到结果集中选CD,与结果集中的边(AC)不构成环,因此将CD放到结果集中选AB,同样不构成环,将AB放到结果集中选AD,此时与结果集中的边构成环(原创 2021-02-23 10:52:38 · 850 阅读 · 0 评论 -
各种排序算法及复杂度、稳定性(左神算法班)
对数器时间复杂度是指常数操作的数量级,以冒泡排序为例:第一次在0 - n-1 范围内找一个最小的数和0位置的数交换,这个过程需要找n次,每次都需要执行取数、比较和交换三个常数操作,因此常数操作需要进行n次第二次在1 - n-1 范围内找一个最小的数和1位置的数交换,这个过程需要找n-1次,每次都需要执行取数、比较和交换三个常数操作,因此常数操作需要进行n-1次重复上述过程那么最后常数操作的次数是(n + n-1 + n-2 + … + 1),这是等差数列,结果为:(n^2/2 + n/2),原创 2021-02-18 22:40:14 · 543 阅读 · 0 评论 -
搜索二叉树及相关习题
单纯的搜索二叉树并不能保证平衡,它的平衡性受制于输入数据,输入的顺序不好(1 2 3 4 5)会导致搜索二叉树变成一条线,这样的时间复杂度是O(n)下面是不同的平衡搜索二叉树AVL树最严格的平衡性,任何一个节点左子树和右子树高度差不超过1,意味着每插入一个数可能都要调整。以下两种树平衡性没有AVL树那么严格,只是在调整的时候策略不同。都能做到增删改查时间复杂度O(logn),差的只是常数项红黑树SB树练习题 大楼轮廓给你一组数:(1,6,4) (2,4,3) (5,8,5) (7,10,2原创 2021-01-13 08:59:40 · 451 阅读 · 0 评论 -
LRU和LFU
LRU双向链表+哈希表class Node { String key; int value; Node pre; Node next; public Node(String key, int value) { this.key = key; this.value = value; }}class biLinkedList{ Node head; Node tail; public biLi原创 2021-01-13 08:59:20 · 88 阅读 · 0 评论 -
左神算法班 单调栈、Morris遍历(前、中、后序)及时间/空间复杂度分析
单调栈解决的问题:对于数组中的每一个数,可以找到这个数左面的最近的比他大的数和右面的最近的比他大的数。例子:3 1 4 2 5,对于1来说,左面距离他最近的且比他大的数是3,右面距离他最近的且比他大的数是4;对于4来说,左面距离他最近的且比他大的数没有,右面距离他最近的且比他大的数是5.如果用暴力法求,那么时间复杂度是O(n^2),因为你要遍历数组中的每一个数,对于每次遍历,都对这个数的左侧与右侧再做一次遍历找到距离他最近的且比他大的值。而单调栈可以在O(n)内求解。理解:现有一数组:[3, 5,原创 2021-01-05 16:54:50 · 1043 阅读 · 0 评论 -
前缀树
对于给出的字符串,从根节点出发,如果能复用边就复用,不能就弄一条新边。但这种结构查询bef的时候会判定be也是给出的字符串,但其实be只是由构建bef附带着得到的,因此用如下结构更好:在每个节点上附加一个值,表示有多少字符串是以到目前为止的字符串结尾的,对于上例来说,e和f之间的节点为0就代表没有字符串以be结尾。上述结构能够找到都有哪些字符串被添加进来了,但无法知道以某段字符串为前缀的字符串有哪些,例如我们不知道有多少字符串以be为前缀。因此在每个节点上再添加一个值,代表此节点被经过了多少次,见.原创 2020-12-20 10:08:57 · 67 阅读 · 1 评论 -
哈希、布隆过滤器与一致性哈希
相同的输入得到相同的结果,不同的输入得到的结果在大样本的情况下在[0, HashSize]内是均匀分布的。推论: 对于若干输入,哈希函数将他们变换后,在结果集上是均匀分布的,那么对每一个变换的值都mod M,则这些结果在[0, M-1]内也是均匀分布的。一个快速获得多个不相关哈希函数的方法:先调用一个哈希函数,将它返回的结果,比如说16位。拆成两半,即前八位和后八位,然后按照下面的方式:h1 + 1 * h2h1 + 2 * h2h1 + 3 * h2…即可得到若干个互不相关的哈希函数。原创 2020-12-18 18:52:42 · 221 阅读 · 0 评论 -
二叉树及相关题目(非递归遍历, 完全二叉树节点数量, 判断是否为搜索二叉树/完全二叉树)
关于二叉树的递归遍历就不写了,这里介绍一下非递归方式二叉树的非递归遍历二叉树结构如下: public static class Node { public intvalue; public Node left; public Node right; public Node(int value) { this.value = value; }先序需要按照根-左-右的方式遍历。所以将根节点压入栈后,先输出它的值。接着看看根节点有无右子树,如果有则把右节原创 2020-12-16 17:06:31 · 205 阅读 · 0 评论 -
数据结构-排序算法之堆排序(C语言实现)
#include<stdio.h>#include<malloc.h>#include<time.h>#define MAX 10void swap(int a[],int pos1, int pos2){ int temp = a[pos1]; a[pos1] = a[pos2]; a[pos2] = temp;}void Heap_Adjust(int a[], int pos, int len){ int max原创 2020-06-27 21:00:04 · 399 阅读 · 0 评论 -
数据结构-排序算法之希尔排序(C语言实现)
#include<stdio.h>#include<time.h>/*和插入排序类似思想是先设一个跳数(通常为: step / 3 + 1),把一组数据分成多组,对多组分别进行插入排序然后缩小跳数,再次重复上述步骤直至跳数为1,也就是对所有数据进行一次插入排序(因为经过前面的操作,全体数据已变的基本有序),从而缩短时间*/#define MAX 10void Shell_sort(int a[], int length){ int step = le原创 2020-06-27 20:59:29 · 415 阅读 · 0 评论 -
数据结构-排序算法之归并排序(C语言实现)
#include<stdio.h>#include<malloc.h>#include<time.h>#define MAX 10int* Creat_Array(){ int* arr = (int *)malloc(sizeof(int) * MAX); srand((unsigned int)time(NULL)); for (int i = 0; i < MAX; i++) { arr[i] =原创 2020-06-27 20:58:46 · 346 阅读 · 0 评论 -
数据结构-排序算法之冒泡排序(C语言实现)
冒泡排序(升、降及其改进)#include<stdio.h>#include<time.h>#define MAX 10void swap(int *a, int *b){ int temp = *a; *a = *b; *b = temp;}void Bubble_sort_descend(int arr[], int length){ for (int i = 0; i < length; i++) {原创 2020-06-19 10:38:23 · 452 阅读 · 0 评论 -
数据结构-排序算法之快速排序(C语言实现)
#include<stdio.h>#include<time.h>/*这是一种不稳定的排序算法,即两个相同元素的相对位置发生了改变:6 2 2 3*/#define MAX 10void Quick_sort(int a[], int start, int end){ if (start >= end) { return; } int i = start; int j = end; int t原创 2020-06-27 20:50:58 · 310 阅读 · 0 评论 -
数据结构-排序算法之选择排序(C语言实现)
#include<stdio.h>#include<time.h>/*和冒泡相似,只不过减少了交换次数大致思想是:先选定一个位置,比如说0,然后依次向后遍历,如果发现某个位置的值比0小,那么先不交换,而是用一个变量temp保存下来,接着向后走,这样一趟下来可以找到数组中最小元素的下标,将其与位置0元素交换,如此第一轮循环后便可将最小的元素放到0号位置。*/#define MAX 10void swap(int *a, int *b){ int temp原创 2020-06-27 20:50:04 · 413 阅读 · 0 评论 -
数据结构-排序算法之插入排序(C语言实现)
#include<stdio.h>#include<time.h>/*效率高的情况:1. 数据基本有序2. 元素个数小 */#define MAX 10void Insert_sort(int a[], int length){ for (int i = 1; i < length; i++) { int j; if (a[i] < a[i-1]) { int原创 2020-06-27 20:48:51 · 258 阅读 · 0 评论