数据结构与算法
重点讲解算法实现的过程
路上的追梦人
尽人事,听天命
展开
-
美团笔试-病毒传播
linux惊群效应详细的介绍什么是惊群,惊群在线程和进程中的具体表现,惊群的系统消耗和惊群的处理方法。1、惊群效应是什么? 惊群效应也有人叫做雷鸣群体效应,不过叫什么,简言之,惊群现象就是多进程(多线程)在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发生,那么他就会唤醒等待的所有进程(或者线程),但是最终却只可能有一个进程(线程)获得这个时间的“控制权”,对该事件进行处理,而其他进程(线程)获取“控制权”失败,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群。 ...原创 2021-07-13 21:25:24 · 199 阅读 · 2 评论 -
一文弄懂差分数组!
差分数组给定一个数组A:A[1]、A[2]、A[3]、A[4]、A[5].......A[i],令数组B为:B[1]、B[2]、B[3]、B[4].......B[i],满足B[1]=A[1],B[2]=A[2]-A[1],B[3]=A[3]-A[2],B[4]=A[4]-A[3],B[5]=A[5]-A[5]........B[i]=A[i]-A[i-1],则称数组B为差分数组。进一步对数组B分析,可以发现数组B的前缀和Sum,存在Sum[i]=B[1]+B[2]+B[3]+B[4]+B[5].原创 2021-07-12 16:11:49 · 217 阅读 · 0 评论 -
LeetCode:求每日的天气变暖的情况
Given a list of daily temperatures T,return a list such that,for each day in the input,tells you how many days you would have to wait until a warmer temperature.If there is no future day for which this is possible,put 0 instead.For example,given the l.原创 2021-01-09 12:10:02 · 246 阅读 · 0 评论 -
LeetCode:利用栈实现队列
尝试使用栈(stack)来实现队列(queue).Example:MyQueue queue=new MyQueue();queue.push(1);queue.push(2);queue.peek();//returns 1queue.pop();//returns 1queue.empty();//return false解题思路:可以使用两个栈来实现一个队列:根据队列先进先出的思想,所以必须有一个额外栈翻转一次数组.这个翻转的数组可以在插入时完成,也可以在取值的时候完成..原创 2021-01-08 19:41:10 · 172 阅读 · 0 评论 -
LeetCode:实现字典树
尝试建立一个字典树,支持快速插入单词、查找单词、查找单词前缀的功能.Example 1:Trie trie=new Trie();trie.insert("apple");trie.search("apple"); //truetrie.search("app"); //falsetrie.startsWith("app");//truetrie.insert("app"); trie.search("app"); //true字典树(Trie)用于判断字符串是否.原创 2021-01-07 10:22:58 · 288 阅读 · 0 评论 -
LeetCode:判断一棵树是否 为平衡二叉树
判断一个二叉树是否平衡.树平衡的定义是,对于树上的任意节点,其左右两侧的子树高度差的绝对值不超过1.解题:方法1:根据左右两侧的子树高度差,可以推测出只要求出这棵树的最大高度与最小高度之间的差值是否满足不超过1,这样就可以判断出是否是平衡二叉树.方法2:后序遍历,需要先处理子树的深度再进行比较,如果在处理过程中发现其已经不平衡了,则可以返回一个-1;#include <iostream>#include <algorithm>using namespace.原创 2021-01-06 14:32:14 · 326 阅读 · 0 评论 -
深入理解数据结构与算法-跳表
一、概述什么是跳表 跳表怎么实现二、跳表1. 跳表的定义和实现意义 我们知道二分查找法的前提是有序数组,那么有没有类似的让链表也证婚词类似"二分"查找的算法,那就是跳表了:它支持快速的插入、删除、查找操作,实现方式没有红黑树那么复杂,甚至可以代替它。Redis的有序集合就是使用跳表实现的, 链表的随机访问数据的时间复杂度是O(n),我们在链表的基础上,每两个结点提取一个结点到上一级,我们把抽出来的那一级叫作索引或索引层。图中的 down 表示 down 指针,指向下一级结转载 2021-01-05 15:01:33 · 206 阅读 · 0 评论 -
深入理解操作系统之页面置换算法
1.最佳(Optimal)置换算法1.1算法原理其选择淘汰的页面将是以后永不使用的,或许是在最长时间内不再被访问的页面.采用最佳置换算法通常可以保证获得最低的缺页率.但由于人们目前还无法预知,一个进程在内存的若干个界面中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用它来评价其他算法.例如:假定系统为某进程分配了三个物理块,并考虑有以下页面号引用串:7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1进程在运行...原创 2020-12-10 13:12:39 · 1412 阅读 · 0 评论 -
LeetCode:员工工资排序
/*题目描述:某公司中有N名员工。给定所有员工工资的清单,财务人员要按照特定的顺序排列员工的工资。他按照工资的频次降序排列。即给定清单中所有频次较高的工资将在频次较低的工资之前出现。如果相同数量的员工都有相同的工资,则将按照给定清单中该工资第一次出现的顺序排列。写一个算法来帮助财务人员排列员工工资的顺序。输入:该函数/方法的输入包括两个参数--num,一个整数,表示员工的人数salaries,一个正整数列表,表示N名员工的工资输出:返回一个正整数列表,该列表按照员工工资的频次排序.原创 2020-11-09 13:27:52 · 1280 阅读 · 0 评论 -
LeetCode-406题:身高重建队列
/*题目描述:假设打乱顺序的一群人站成一个队列。每个人由一个整数对(h,k)表示,其中h是这个人的身高,k是排在这个人前面而且身高大于或等于h的人数。编写一个算法来重建这个队列。示例:输入:[[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]*//*思路:当两个人的高度h相同时,k比较大的往后排;两个人高度不同时,“个子矮的”对于个子高的来说是不可见的,默认人数为0;所以先根据高度(降..原创 2020-10-29 21:44:16 · 141 阅读 · 0 评论 -
面试-define与typedef的区别
一、#define1.简单的define定义#defineMAXTIME 1000这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为define的定义更像是简单的文本替换,而不是作为一个量来使用,这个问题在下面反映的尤为突出。2.define的“函数定义”define可以像函数那样接受一些参数,如下#definemax(x,y) (x)>(y)?(x):(y);定义就将返回两个数中较大的那个。因为这个“函数”没有类型检查,就好像一个函数模板似...转载 2020-10-13 11:13:01 · 176 阅读 · 0 评论 -
深入理解C++构造函数初始化列表与赋值
在C++中类成员变量的初始化有以下两种方式:构造函数初始化列表; 构造函数体内赋值;内部数据类型形如char,int,float…指针等class Animal{public: Animal(int weight,int height): //A初始化列表 m_weight(weight), m_height(height) { } Animal(int weight,int height) ...原创 2020-10-11 13:58:53 · 11259 阅读 · 3 评论 -
一文搞懂共享锁、排他锁、悲观锁、乐观锁、行锁、表锁
我们在操作数据库的时候,可能会由于并发问题而引起的数据的不一致性(数据冲突)。共享锁(S锁)共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。 如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。排他锁(X锁)用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。 如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁.转载 2020-10-10 20:25:12 · 3802 阅读 · 1 评论 -
Mysql三大日志-binlog、redo log和undo log
日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。作为开发,我们重点需要关注的是二进制日志(binlog)和事务日志(包括redo log和undo log),本文接下来会详细介绍这三种日志。binlogbinlog用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlog是mysql的逻辑日志,并且由Server层进行记录,使用任何存储引擎的mysql数据库都会记转载 2020-10-10 13:33:12 · 91 阅读 · 0 评论 -
一文搞懂面试中的mysql事务和锁
众所周知,事务和锁是mysql中非常重要功能,同时也是面试的重点和难点。本文会详细介绍事务和锁的相关概念及其实现原理,相信大家看完之后,一定会对事务和锁有更加深入的理解。本文主要内容是根据掘金小册《从根儿上理解 MySQL》整理而来。如想详细了解,建议购买掘金小册阅读。什么是事务在维基百科中,对事务的定义是:事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。事务的四大特性事务包含四大特性,即原子性(Atomicity)、一致性(Consis转载 2020-10-10 13:02:51 · 248 阅读 · 0 评论 -
模板类成员变量的构造函数的初始化
在C++类中,形如int型变量没有带参数的初始化默认是0,float k = 0;float = float();float tmp = float(0); // 这是 (显示转换)explicit cast以上代码都是等价的。在C++为非类类型(non-class type,或称原生类型),这里的意思是提供的缺省构造函数(deconstructor),就方便处理模板参数。template<typename T>class solution{public:原创 2020-10-10 09:47:35 · 1732 阅读 · 0 评论 -
一文搞定基址寄存器、界限寄存器、静态重定位与动态重定位
地址空间是一个进程可用于寻址内存的一套地址集合。每个进程都有一个自己的地址空间,并且这个地址空间独立于其他进程的地址空间(除了在一些特殊情况下进程需要共享它们的地址空间外)。给每个程序一个自己的地址空间,使得一个程序中的地址28所对应的物理地址与另一个程序中的地址28所对应的物理地址不同。方法:基址寄存器与界限寄存器使用一种简单的动态重定位,把每个进程的地址空间映射到物理内存的不同部分。当使用基址寄存器和界限寄存器时,程序装载到内存中连续的空闲位置且装载期间无须重定位,如图3-2c所示。当一.转载 2020-10-09 10:29:32 · 8719 阅读 · 2 评论 -
C++ 函数把引用作为返回值
通过使用引用来替代指针,会使 C++ 程序更容易阅读和维护。C++ 函数可以返回一个引用,方式与返回一个指针类似。当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。例如,请看下面这个简单的程序:#include <iostream> using namespace std; double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0}; double& setValues( int i ).原创 2020-10-07 18:07:35 · 348 阅读 · 0 评论 -
STL-erase与remove讲解
erase:从指定容器删除指定的元素两个重载:iterator erase (iterator position);删除指定位置position的元素,并返回删除元素的下一个元素的迭代器iterator erase (iterator first, iterator last);删除从first到last(不包过last)之间的元素 [first,last),并返回last位置迭代器错误用法1#include<vector>#include<iostre.转载 2020-10-06 20:01:44 · 337 阅读 · 0 评论 -
深入理解端口与IP的关系
IP:网络之间互连的协议(IP)是Internet Protocol的外语缩写, 中文缩写为“网协”.网络之间互连的协议也就是为计算机网络相互连接进行通信而设计的协议。在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守IP协议就可以与因特网互连互通。IP地址具有唯一性,根据用户性质的不同,可以分为5类。另外,IP还有进入防护,知识产权,指针寄存器等含义。端口:"端口"是英文port的意转载 2020-10-06 16:50:48 · 20322 阅读 · 0 评论 -
笔记-深入理解Redis分布式缓存
今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等概念一、缓存雪崩缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。缓存正常从Redis中获取,示意图如下:缓存失效瞬间示意图如下:缓存失效时的雪崩效转载 2020-10-06 15:51:46 · 144 阅读 · 0 评论 -
笔记-解剖类成员变量多用指针,而不是对象
class A{ //};class B{private: A* a;public: void fun(A* a); //};如A类的成员变量含有B类的对象,那么每个A类对象产生或拷贝都要产生一次B类对象的构造或者拷贝,对象占的空间比较大,对象拷贝比较消耗内存。如果换成B类的指针,A类对象拷贝,也只会产生4个字节(32位操作系统)或者8个字节(64位操作系统)的拷贝。传指针(和引用)是非常快的,A* a这种形式 在传参数的时候,会首先调用类A的赋值构..原创 2020-10-06 14:15:50 · 254 阅读 · 0 评论 -
笔记-Git的讲解
转载于https://blog.csdn.net/YJG7D314/article/details/104551896目录1.git 简介1.1 产生历史1.2 git两大特点2.安装配置3.创建一个版本库4.版本的创建与回退4.1 使用4.2 工作区和缓存区4.2.1 工作区(WorkingDirectory)4.2.2 版本库(Repository)4.3 管理修改4.4 撤销修改4.5 对比文件的不同4.6 删除文件5. 分支管理.转载 2020-10-02 18:38:54 · 575 阅读 · 0 评论 -
笔记-traits技巧讲解
侯捷老师在《STL源码剖析》中说到:了解traits编程技术,就像获得“芝麻开门”的口诀一样,从此得以一窥STL源码的奥秘。如此一说,其重要性就不言而喻了。 之前已经介绍过迭代器,知道了不同的数据结构都有自己专属的迭代器,不同的迭代器也有不同的特性,由于算法的接口是统一的,通过迭代器的不同属性,算法自动选择正确的执行流程,在完全任务的同时,也尽可能提高算法的执行效率。那算法如何获知迭代器的属性呢?这一光荣的任务就是traits完成的。在STL实现中,traits编程技术得到大量的运用...转载 2020-10-01 20:25:59 · 800 阅读 · 0 评论 -
笔记-空间配置器详解
空间配置器1.什么是空间配置器为各个容器高效的管理空间(空间的申请与回收)的2.为什么需要空间配置器各种容器----->可以存放元素---->底层需要空间new 申请空间operator new ---->malloc 调用构造函数------完成对象的构造动态内存管理总结前面的容器中,每次开辟空间都用的是new,但是用new有一些不好的地方空间申请与释放需要用户自己管理,容易造成内存泄漏 频繁向系统申请小块内存块,容易造成内存碎片例如:结点 频繁转载 2020-10-01 19:39:18 · 382 阅读 · 0 评论 -
笔记-数据结构之哨兵
设置哨兵是为了减少比较次数,省去对下标越界的判断。应用:假设一个乱序数组,需要查找一个元素是否在该数组中,这时需要用到顺序查找,也就是遍历数组。一般情况下我们会写下如下代码:int Sequential_Search(int *a,int n,int key) { //数组从1开始 int i; for(int i=1;i<=n;i++) { if(a[i]==key) return i;转载 2020-10-01 13:48:19 · 1181 阅读 · 0 评论 -
笔记-类对象动态数组
默认构造函数首先,我们来看一下是什么是默认构造函数,如下面一段代码:#include<iostream>#include<math.h>using namespace std;class Point{ double x, y;public: void print(); Point(double a=0,double b=1){x=a;y=b;} //默认构造函数 Point(double a){x=1;y=1;} //构造...转载 2020-09-29 21:39:42 · 1444 阅读 · 0 评论 -
笔记-类的保护成员
在类的外部,应当把保护成员和私有成员同等看待,都不允许对象直接进行访问; 在类的内部,若类之间存在继承关系,则派生类可以访问基类保护成员,不可以访问基类私有成员,而且派生类在类内也只能通过派生类对象的形式访问基类的保护成员。派生类对于基类对象的保护成员没有任何访问特权; 公有成员则是暴露的,随时处在风口浪尖之中 只有baipublic类型的变量才可以被该类的对象du直接访问。基类的对象zhi和派生类的对象都不能直接访问类dao的保护成员和私有成员。...原创 2020-09-29 15:34:44 · 1802 阅读 · 0 评论 -
宿主机访问本机虚拟机中的web服务器
虚拟机网络选择NAT模式,linux系统使用ifconfig命令,查看ip地址,然后安装Apache并启动,虚拟主机内打开浏览器,访问localhost,访问正常,然后关闭防火墙 systemctl stop firewalld。此时本机输入刚刚查看到的ip地址即可访问。涉及到的指令:APache服务器常用指令systemctl start httpd.servicesystemctl status httpd.servicesystemctl stop httpd.ser...转载 2020-09-28 11:36:26 · 4090 阅读 · 0 评论 -
笔记-poll/select/epoll
poll/select/epoll 对比http://www.cnblogs.com/apprentice89/p/3234677.html ---有待继续学习http://blog.chinaunix.net/uid-20384806-id-1954307.html ---有待继续学习select和poll即使只有一个描述符就绪,也要遍历整个集合。如果集合中活跃的描述符很少,遍历过程的开销就会变得很大,而如果集合中大部分的描述符都是活跃的,遍历过程的开销又可以忽略。...转载 2020-09-27 15:07:38 · 243 阅读 · 0 评论 -
一文搞懂异步、并发、协程原理
异步、并发、协程原理Linux 操作系统在设计上将虚拟空间划分为用户空间和内核空间,两者做了隔离是相互独立的,用户空间给应用程序使用,内核空间给内核使用。一、异步应用程序和内核内核具有最高权限,可以访问受保护的内存空间,可以访问底层的硬件设备。而这些是应用程序所不具备的,但应用程序可以通过调用内核提供的接口来间接访问或操作。所谓的常见的 IO 模型就是基于应用程序和内核之间的交互所提出来的。以一次网络 IO 请求过程中的 read 操作为例,请求数据会先拷贝到系统内核的缓冲区(内核空间),再转载 2020-09-26 18:28:12 · 1821 阅读 · 1 评论 -
一文搞懂类的继承和多态
一:继承继承的概念:为了代码的复用,保留基类的原始结构,并添加派生类的新成员。继承的本质:代码复用我们用下图解释下:那么我们这里就可以提出几个问题了:①:进程的方式有哪些呢?这里有三种继承方式:public:任意位置可以访问 protected:只允许本类类中以及子类类中访问 private:只允许本类类中访问②:派生类继承了基类的什么?所有成员变量,包括static静态成员变量 成员方法,除构造和析构以外的所有方法 作用于也继承了,但是...转载 2020-09-26 09:58:03 · 1499 阅读 · 0 评论 -
Reactor设计模式
Reactor 反应堆设计模式为了应对高并发的服务器端开发,微软在2009年提出了一种更优雅地实现异步编程的方式Reactive Programming即反应式编程。随后其他技术紧随其后,比如ES6通过引入类似的异步编程方式等。在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,Proactor用于异步I/O操作。Reactor模式称之为响应器模式,通常用于NIO非阻塞IO的网络通信框架中。在这之前,需要弄明白几..转载 2020-09-25 15:43:06 · 364 阅读 · 0 评论 -
项目实战-Http服务器
目录从main函数开始 初始化函数startup(&port) 请求处理accept_request(&client_sock) 请求行的处理 本地处理 测试结果 服务器功能测试 使用webbench测试 Tinyhttpd是一个小型的http服务器实现,代码仅仅500行,我在大致过了一下unix环境编程之后就想找一个web服务器来练练手,这个就作为俺第一个web方向的小项目吧。看完这个代码后准备研究一下muduo库、Nginx和Redis,上.转载 2020-09-25 15:13:31 · 309 阅读 · 0 评论 -
一文弄懂连接池和线程池
线程池线程池的原理类似于操作系统中的缓冲区的概念。先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。也许有人质疑:为什么要搞得这么麻烦,如果每当客户端有新的请求时,我就创建一个新的线程不就完了吗?这也许是个不错的方法,因为它能使你的代码相对容易一些,但是却忽略了性能问题。假如有一个省级数据大集中的银行网络中心,高峰期每秒的客户端请求并发数超过100,如果为每个客户端请转载 2020-09-24 20:45:55 · 963 阅读 · 0 评论 -
一文搞懂TCP和UDP的区别
TCP协议与UDP协议的区别首先咱们弄清楚,TCP协议和UDP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信!TCP/IP协议是一个协议簇。里面包括很多协议的,UDP只是其中的一个, 之所以命名为TCP/IP协议,因为TCP、IP协议是两个很重要的协议,就用他两命名了。TCP/IP协议集包括应用层,传输层,网络层,网络访问层。其中应用层包括:1、超文本传输协议(HTTP):万维网的基本协议;2、文件传输(T转载 2020-09-24 15:46:05 · 633 阅读 · 0 评论 -
一分钟弄懂线程程序计数器
程序计数器为什么是线程私有的?1.程序计数器1.1.程序计数器的本质从本质来看,程序技术器就是一块比较小的内存空间。1.2.程序计数器的作用程序计数器可以看作是当前线程所执行字节码的行号指示器,也就是说,程序计数器这块小空间里面记录的是当前线程正在执行的字节码的行号。字节码解释器通过改变计数器的值来获取下一条要执行的字节码。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。1.3.为什么程序计数器被设计成线程私有的?假如现在有一本书,有好几个同学都...转载 2020-09-23 14:25:40 · 1204 阅读 · 0 评论 -
深入理解类组合构造函数的初始化
在一个类中内嵌套另一个类的对象作为数据成员,这样可以称为类的组合。类中的成员数据是另一个类的对象。通过类的组合可以在已有的抽象的基础上实现更复杂的抽象。该内嵌对象称为对象成员,或者子对象。如学生类Student的内嵌课程类Course作为数据成员;class Student{private: Course *m_course;public:};在使用过程中,需要着重注意的是对象成员的初始化!如Student的构造函数该如何定义?如果一个类具有内嵌对象,那么在它对象化的时..转载 2020-09-23 10:13:29 · 497 阅读 · 0 评论 -
两分钟搞定POSIX
在网上查到对于posix的介绍,来自《Linux内核设计与实现(第2版)》的第5章,就这部分来看,这本书估计不错。 一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程。这点很重要,因为应用程序使用的这种编程接口实际上并不需要和内核 提供的系统调用对应。一个API定义了一组应用程序使用的编程接口。它们可以实现成一个系统调用,也可以通过调用多个系统调用来实现,而完全不使用任何系 统调用也不存在问题。实际上,API可以在各种不同的操作系统上实现,给应用程序提供完全相同的接口,而它们本身.转载 2020-09-21 15:27:50 · 374 阅读 · 0 评论 -
难点解刨-Posix消息队列
Posix消息队列目录1. 概述 2. Posix消息队列 创建与打开 关闭与删除 消息队列属性 获取属性 设置属性 消息发送与接收 3. 消息队列限制 4. 生产者消费者问题——Posix消息队列实现 单生产者 + 单消费者 多生产者 + 单消费者 5. 效率对比1. 概述消息队列可认为是一个消息链表,队列中的每个消息具有如下属性:消息优先级,由发送者赋予 消息数据长度,可以为0 消息...转载 2020-09-21 14:25:15 · 471 阅读 · 1 评论