数据结构与算法
数据结构与算法,主要是C/C++实现
ka__ka__
软件工程师
展开
-
基于邻接矩阵的朴素Dijkstra单源最短路C++极简实现
基于邻接矩阵的Dijkstra实现使用C++,可以方便的写出一个通用的朴素dijkstra极简实现,核心逻辑不超过20行。#include <vector>#include <algorithm>#include <cstdio>using namespace std;vector<int> dijkstra(vector<vector<int>> &graph, int start){ const i原创 2020-08-16 01:08:36 · 526 阅读 · 0 评论 -
sys/queue使用说明与TAILQ使用举例
每个写C的同学想必都会羡慕C++方便的STL,但是无奈标准C是没有这些库的,毕竟C语言不支持泛型,不过好在大多数Linux下都可用sys/queue,源自BSD:https://unix.superglobalmegacorp.com/xnu/newsrc/bsd/sys/queue.h.html这个头文件用宏实现了很多基础数据结构,如:单链表、双链表、队列等。用起来也比较方便,只需要引入一个头文件即可。如著名的的libevent项目就大量使用了这个头文件里的TAILQ. 不过C的宏实现的库并没有C++原创 2020-07-31 00:36:53 · 967 阅读 · 0 评论 -
DFS递归回溯求排列组合的C实现
深度优先搜索DFS本身很好理解,即按照一定顺序递归遍历一个图,但是如何把所有的满足要求的遍历方式给求出来,这里就需要结合回溯backtrace了。在LeetCode中,回溯标签下的很多题目都是求排列组合的,这也算是一类经典类型的题目了。C/C++写的多人都会有个特点:写代码的时候脑子里都是内存布局,栈帧结构,以及代码执行时各个对象的生命周期等等,写的多了某种程度可以对这些东西做到可视化了都。理解...原创 2019-10-25 08:28:12 · 727 阅读 · 0 评论 -
基于邻接表的有回溯最小堆优化的单源最短路Dijkstra算法
前一篇blog的图的存储结构用的邻接矩阵,这篇使用邻接表。不同的数据结构特点也不同,要根据算法需要选出合适的。图规模比较小时,推荐邻接矩阵;稠密图推荐用邻接矩阵;需要快速判断两点间是否右边,推荐邻接矩阵;稀疏图推荐用邻接表;这里还是选取这篇文章中的例子,文章中附有图,这里基于邻接表实现,代码如下:#include <cstdio>#include <cstring>#include <原创 2016-10-20 23:57:05 · 1096 阅读 · 2 评论 -
基于邻接矩阵的有回溯最小堆优化的单源最短路Dijkstra算法
前面的一篇笔记最短路没有带回溯,这里补充一个带回溯版本的,算法还是 Dijkstra 算法,前面的笔记:算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法,例子还是那个那篇笔记的例子,图存储结构还是邻接矩阵,算法封装到了一个类中,代码如下:#include <algorithm>#include <cstdio>class Graph {private: int *gra原创 2016-10-16 13:24:19 · 1332 阅读 · 0 评论 -
小练习 - 哈希表之分离链接法
小练习 - 哈希表之分离链接法哈希表十分常用,这里做个小练习,冲突解决使用分离链接发。从哈希表的C语言实现角度来看,Hash本质上做了这样一个映射:key -> hashtable[index] -> addr, 新插入一个数据时,key由数据本身决定,存储地址addr则是系统分配,key通过哈希函数可以算出索引,查找索引对应哈表项目得到地址。采用分离链接法,底层数据结构主要是数据和单链表。这里未考原创 2017-03-18 01:03:24 · 823 阅读 · 0 评论 -
小练习 - 单链表冒泡排序,交换指针域
链表的排序,好的做法是交换指针域。链表节点的数据域可能比较大,交换数据域可能会涉及拷贝过多的内存,影响性能。链表是链式存储,无法随机访问(base_addr + offset), 所以比较适合的办法是用比较两两相邻节点的冒泡排序法。当然还有一个办法就是,把所有的链表地址存到一个数组里,排序后重新遍历设置所有指针域,这个就多了两次遍历,也可以。下面是交换指针域的一个单链表冒泡排序的例子:#inc...原创 2018-02-18 14:29:54 · 2524 阅读 · 2 评论 -
C语言实现极简递归下降JSON parser解析器
JSON字符串解析利用递归下降非常容易实现。本文实现了一个不支持数组,数字解析只支持正数long类型,只支持ASCII字符集的极简JSON解析器,未实现的功能后面也比较容易扩展。原创 2019-04-28 23:47:39 · 1212 阅读 · 0 评论 -
小练习 - C语言实现一个极简通用vector
C语言库比较少,很大的原因就是没有泛型,也没有class。但是C语言作为一个较为底层的系统级语言,操纵内存还是很灵活的。模仿C++实现一个泛型vector,可以使用void*,使用的时候强转对应类型,或者使用宏来封装一些操作。这里实现一个极简的vector,拥有增删查功能,存储的元素放在连续内存中,扩容时1.5倍增长。没有加锁,非线程安全。这个可以在控制结构体里添加。原理很简单,内存不够了,ma...原创 2019-08-21 22:11:36 · 1010 阅读 · 0 评论 -
C语言侵入式链表
C语言虽然没有泛型,但是拥有对内存的终极解释权限,这个也带给了C语言强大的表达能力。对于复杂数据结构,侵入式链表绝对是一个好的经典实现,Linux Kernel 在 2.1 之后就使用 list_head 的内嵌来实现双向循环链表。而且,glibc也提供了这种实现的标准库 glibc/include/list.h。对于C语言项目,有时候会需要精细规划内存使用。这时设计数据结构时,通常都是存储和控...原创 2018-10-26 23:38:28 · 2061 阅读 · 1 评论 -
小练习 - 排序:冒泡、选择、快排
好久没手写过排序了,用C89标准的C重新练习下三种排序方法,快排的边界还是需要注意下。练习这些经典算法要在脑子里能够形象的想象出这些数据结构的表现与操作,这样才能理解深刻。// c89 标准#include <stdio.h>// [begin, end) 前闭后开,索引范围是[begin, end - 1]// 冒泡, 稳定排序void bubble_sort(int data[], int原创 2017-02-02 22:07:29 · 581 阅读 · 0 评论 -
小练习 - 基于链表的栈和队列
随手练下基本的数据结构,基于链表实现一个动态大小的栈和队列,最基本简单的数据结构要注意各种边界场景。基于链表实现,频繁增删调用mallc会带来一定开销,实际使用要看情况来定。基于链表的栈typedef struct _node { int data; struct _node* next;}node;typedef struct _stack { node *top;原创 2017-03-10 00:13:41 · 457 阅读 · 0 评论 -
算法学习笔记(二) 面试
面试考察的能力和态度:学习能力,考察其在工作过程中是否能够积极获取与工作有关的信息和知识,并对获取的信息进行加工和理解,从而不断地更新自己 的知识结构、提高自己的工作技能。积极主动的态度,一种积极、乐观、提前行动的思维方式,碰到困难时不抱怨, 而是积极的寻找更为有效的行动来规避或解决。保持高度竞争性,主动寻求自我提升与发展,超越自我。原创 2014-05-25 21:47:35 · 1957 阅读 · 0 评论 -
算法学习笔记(八) 动态规划的一般求解方法
1 一个问题:换零钱方式的统计SICP 第一章 1.2.2 树形递归中,有这么一问题:给了半美元,四分之一美元,10美分,5美分和1美分的硬币,将1美元换成零钱,一共有多少种不同方式?更一般的问题是,给定了任意数量的现金,我们能写一个程序,计算出所有换零钱方式的种数吗?2 动态规划的基本模型动态规划(Dynamic programming,DP),是研究一类最优化问题的方法,通过把原问...原创 2014-11-13 08:49:42 · 5945 阅读 · 1 评论 -
算法学习笔记(四) KMP算法之 next 数组详解
最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n.其中,比较难理解的地方就是 next 数组的求法。原创 2014-08-13 23:18:31 · 3203 阅读 · 2 评论 -
算法学习笔记(九)有限状态机 FSM 的应用
有限状态机(Finite-state machine)又称有限状态自动机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。常用与:正则表达式引擎,编译器的词法和语法分析,游戏设计,网络协议,企业应用中等方面。这里给出其一般实现方法和一个应用举例。原创 2014-11-16 13:06:26 · 7776 阅读 · 0 评论 -
算法学习笔记(七) 平衡二叉树 AVL树
AVL树是最先发明的自平衡二叉查找树, 其增删查时间复杂度都是 O(logn), 是一种相当高效的数据结构。当面对需要频繁查找又经常增删这种情景时,AVL树就非常的适用。AVL树定义AVL树诞生于 1962 年,由 G.M. Adelson-Velsky 和 E.M. Landis 发明。AVL树首先是一种二叉查找树。二叉查找树是这么定义的,为空或具有以下性质:若它的左子树不空,则左子...原创 2014-09-14 20:39:18 · 2606 阅读 · 0 评论 -
算法学习笔记(六) 二叉树和图遍历—深搜 DFS 与广搜 BFS
复习下二叉树和图的深搜与广搜。从图的遍历说起,图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search)。图搜索的经典应用走迷宫、N皇后、二叉树遍历等。遍历:定义按某种顺序访问“图”中所有的节点。原创 2014-08-24 12:17:08 · 5219 阅读 · 0 评论 -
算法学习笔记(五) 递归之 快速幂、斐波那契矩阵加速
递归就是直接或间接调用自身。算法思想:原问题可分解子问题(必要条件),原与分解后的子问题相似(递归方程),分解次数有限(子问题有穷),最终问题可直接解决(递归边界),经典问题有:幂运算、阶乘、组合数、斐波那契数列、汉诺塔等。这里详细介绍:快速幂的实现;斐波那契数列的矩阵加速实现;原创 2014-08-17 20:19:28 · 4887 阅读 · 1 评论 -
C/C++用状态转移表联合函数指针数组实现状态机FSM
状态机在工程中使用非常的频繁,有如下常见的三种实现方法:1. `switch-case` 实现,适合简单的状态机;2. 二维状态表`state-event`实现,逻辑清晰,但是矩阵通常比较稀疏,而且维护麻烦;3. 用状态转移表`stateTransfer Table`实现,数组大小等于状体转移边个数,易扩展;原创 2015-07-26 16:49:39 · 3816 阅读 · 0 评论 -
算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法
图论中一个经典问题就是求最短路,最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划,这也是算法中的两大经典代表。用一个简单图在纸上一步一步演算, 带回溯的笔记在这篇。对于平时的练习,一个很厉害的 ACMer 说:“刷水题可以加快我们编程的速度,做经典则可以让我们触类旁通,初期如果遇见很多编不出,不妨就写伪代码,理思路,在纸上进行整体分析...原创 2014-06-20 16:54:41 · 4621 阅读 · 0 评论 -
算法学习笔记(一) 概述
算法的重要性系统的学习算法对一个程序员是十分有必要的。MIT 讲授《算法导论》的 Erik Demaine 教授说过:If you want to become a good programmer, you can spend 10 years programming, or spend 2 years programming and learning algorithms.算法的学习原创 2014-05-25 20:24:50 · 2669 阅读 · 0 评论