数据结构和算法
数据结构和算法
狂奔的乌龟
1、博客介绍:专注分享ARM Trustzone/TEE/Linux/嵌入式等领域知识,大部分是个人学习笔记,关注我,一起学习!希望在这里能和大家一起进步,星光不负赶路人,加油!
2、个人介绍:ARM/TEE/Linux等领域忠实爱好者,个人长期专注于硬件安全、系统安全、嵌入式领域安全开发工作。
3、个人语录:积累是一个漫长的过程,未来很长,一起努力,只要路是对的,就不怕路远。
4、招聘广告:目前在国内大厂上班,长期招聘高级别&有经验的硬件安全、系统安全、嵌入式底层软件架构师&SE&MDE,寻求志同道合有志之士,有意向可私信我。
展开
-
算法学习之循环和递归
【摘要】 大家都知道递归的实现是通过调用函数本身,函数调用的时候,每次调用时要做地址保存,参数传递等,这是通过一个递归工作栈实现的。原理上讲,所有递归都是可以消除的,代价就是可能自己要维护一个栈。而且我个人认为,很多情况下用递归还是必要的,它往往能把复杂问题分解成更为简单的步骤,而且很能反映问题的本质。循环和递归其实存在一定的联系。 1)求和递归函数 我们可以举一个循环的例子,前面我们说过,如果编写一个1到n的求和函数怎么写呢,你可能会这么写:int calculate(int m){ in原创 2015-06-17 16:32:26 · 767 阅读 · 0 评论 -
算法学习之排序算法(三)(选择排序法)
选择排序工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。选择排序是和冒泡排序差不多的一种排序。和冒泡排序交换相连数据不一样的是,选择排序只有在确定了最小的数据之后,。原创 2015-08-13 21:55:38 · 893 阅读 · 0 评论 -
算法学习之排序算法(四)(希尔排序)
希尔排序的基本思想是把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序。原创 2015-08-15 19:14:12 · 1009 阅读 · 0 评论 -
并发无锁队列学习(概念介绍)
【摘要】队列在计算机中非常重要的一种数据结构,尤其在操作系统中。队列典型的特征是先进先出(FIFO),符合流水线业务流程。在进程间通信、网络通信之间经常采用队列做缓存,缓解数据处理压力。结合自己在工作中遇到的队列问题,总结一下对不同场景下的队列实现。根据操作队列的场景分为:单生产者——单消费者、多生产者——单消费者、单生产者——多消费者、多生产者——多消费者四大模型。其实后面三种的队列,可以归纳为一种多对多。根据队列原创 2015-07-24 19:23:56 · 7144 阅读 · 0 评论 -
并发无锁队列学习(数据结构)
提到并行计算通常都会想到加锁,事实却并非如此,大多数并发是不需要加锁的。比如在不同电脑上运行的代码编辑器,两者并发运行不需要加锁。在一台电脑上同时运行的媒体播放放器和代码编辑器,两者并发运行不需要加锁(当然系统调用和进程调度是要加锁的)。在同一个进程中运行多个线程,如果各自处理独立的事情也不需要加锁(当然系统调用、进程调度和内存分配是要加锁的)。在以上这些情况里,各个并发实体之间没有共享数据,所以虽转载 2015-07-24 19:35:12 · 2533 阅读 · 0 评论 -
并发无锁队列学习(单生产者单消费者模型)
【摘要】本文介绍单生产者单消费者模型的队列。根据写入队列的内容是定长还是变长,分为单生产者单消费者定长队列和单生产者单消费者变长队列两种。单生产者单消费者模型的队列操作过程是不需要进行加锁的。生产者通过写索引控制入队操作,消费者通过读索引控制出队列操作。二者相互之间对索引是独享,不存在竞争关系。原创 2015-07-24 19:45:10 · 4992 阅读 · 1 评论 -
数据结构学习之 union 共用体(union 到底有什么用?)
1、引言共用体常用来节省内存,特别是一些嵌入式编程,内存是非常宝贵的! 共用体也常用于操作系统数据结构或硬件数据结构! union 在操作系统底层的代码中用的比较多,因为它在内存共享布局上方便且直观。所以网络编程,协议分析,内核代码上有一些用到 union 都比较好懂,简化了设计。共用体(union)是一种数据格式,它能够存储不同类型的数据,但是只能同时存储其中的一种类型。主要用处分以下3个方面原创 2015-09-08 16:11:33 · 8801 阅读 · 1 评论 -
算法学习之排序算法(五)(快速排序)
1、算法思想设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。一趟快速排序的算法是: 1)设置两个变量i、j,排序开始的时候:i=0,j=N-1; 2)原创 2015-08-19 21:47:56 · 921 阅读 · 0 评论 -
堆栈顺序存储和 free 失败原因分析
*** Error in `./a.out': free(): invalid pointer: 0x09e7c018 ***======= Backtrace: =========/lib/i386-linux-gnu/libc.so.6(+0x767c2)[0xb76307c2]/lib/i386-linux-gnu/libc.so.6(+0x77510)[0xb7631510]./a原创 2015-10-19 17:20:08 · 1987 阅读 · 0 评论 -
数据结构学习之堆栈(顺序存储)
堆栈顺序存储,基于连续内存的操作。 主要关于怎么创建堆栈,出栈,入栈等等操作。原创 2015-06-19 09:29:16 · 3847 阅读 · 0 评论 -
数据结构学习之堆栈(链式存储)
【摘要】链表存储结构的内存地址不一定是连续的,但顺序存储结构的内存地址一定是连续的;链式存储适用于在较频繁地插入、删除、更新元素时,而顺序存储结构适用于频繁查询时使用。所以本文主要基于前文的基础,讨论链式存储结构的堆栈。1、链式存储(不连续内存)/*链式结构*/typedef struct _STACK_NODE{ int pData; struct _STACK_NODE *n原创 2015-06-19 09:40:41 · 2462 阅读 · 1 评论 -
[LeetCode-28] Implement strStr(KMP 字符串匹配)
1、KMP算法的思想由D.E.Knuth、J.H.Morris和V.R.Pratt共同提出了一个改进算法,消除了Brute-Force算法中串s指针的回溯,完成串的模式匹配。时间复杂度为O(s.curlen+t.curlen),这就是Knuth-Morris-Pratt算法,简称KMP 算法。2、经典的next求解方法《大话数据结构》 P141页原创 2015-11-20 17:59:41 · 1368 阅读 · 0 评论 -
算法学习之字符串匹配 KMP 算法(一)(原理介绍)
下面,我用自己的语言,试图写一篇比较好懂的KMP算法解释。 1. 首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。 2. 因为B与A不匹配,搜索词再往后移。 3. 就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止。 4.转载 2015-11-18 21:41:14 · 513 阅读 · 0 评论 -
数据结构学习之循环队列(顺序存储)
【摘要】队列特性:先进先出(FIFO)——先进队列的元素先出队列。来源于我们生活中的队列(先排队的先办完事)。 这样有个缺陷,空间利用率不高,所以我们直接学习循环队列(基于连续内存的)。 (1)设计队列数据结构typedef struct _QUEUE_NODE{ int* pData; int length;//队列长度 int head ;//队头指针原创 2015-06-19 11:07:12 · 1386 阅读 · 2 评论 -
算法学习之排序算法(一)(冒泡法)
冒泡排序的内容并不复杂。假设有n个数据需要排序,那么我们需要确定n个从大到小的数据,每一次都挑选第n大的数据是多少,并且放大相应的位置。直到所有的数据都排列整齐了,那么我们的排序就结束了。 1、冒泡代码void bubble_sort(int array[], int length){ int inner = 0, outer = 0; int median = 0; if原创 2015-08-12 21:25:46 · 1070 阅读 · 0 评论 -
算法学习之排序算法(二)(直接插入排序法)
1、插入法排序原理直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。原创 2015-08-12 21:34:58 · 941 阅读 · 0 评论 -
assert() 宏用法
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:#include <assert.h>void assert( int expression ); assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。请看下面的程序清单badptr.c:复制代码#include <stdio.h>#include <assert.h>#inc原创 2015-06-17 15:47:40 · 834 阅读 · 0 评论 -
算法学习之递归和堆栈
【摘要】当执行完被调用函数,返回外部程序前,系统首先要恢复外部程序的变量当前值,然后返回外部程序的返回地址。递归函数被外部程序调用时,系统要做的工作和非递归函数被调用时系统要做的工作在形式上类同,只是实现方法不同而已。那递归代码和运行时的堆栈有什么关系呢?我们先看一下下面这几幅图,关于递归代码和运行时堆栈关系。 我们可以看一下普通函数的调用怎么样的。试想如果函数A调用了函数B,函数B又调用了函数C,那么在堆栈中的数据是怎么保存的呢?[cpp] view plaincopy函数A ^原创 2015-06-17 16:52:23 · 2733 阅读 · 0 评论 -
速查表:常用算法和数据结构的复杂度
【摘要】常用算法和数据结构的复杂度速查表转自http://top.jobbole.com/1599/算法数据结构时间复杂度空间复杂度 平均最差最差深度优先搜索 (DFS)Graph of |V| vertices and |E| edges-O(|E| + |V|)O(|V|)广度原创 2015-06-17 19:58:55 · 1072 阅读 · 0 评论 -
算法学习之查找(顺序、二分法、排序二叉树以及 Hash 表)
【摘要】查找—-用关键字标识一个数据元素,查找时根据给定的某个值,在表中确定一个关键字的值等于给定值的记录或数据元素。在计算机中进行查找的方法是根据表中的记录的组织结构确定的。查找功能数据处理的一个基本功能。数据查找并不复杂,但是如何实现数据又快又好地查找呢?前人在实践中积累的一些方法,值得我们好好学些一下。我们假定查找的数据唯一存在,数组中没有重复的数据存在。1、 顺序查找设想有一个1M的数据,我原创 2015-06-17 19:35:34 · 4957 阅读 · 2 评论 -
数据结构学习之双向循环链表的基本操作(非递归实现)
【摘要】前一篇博客阐述了循环单链表,它虽然能够实现从任一结点出发沿着链能找到其前驱结点,但时间耗费是O(n)。如果希望从表中快速确定某一个结点的前驱,另一个解决方法就是在单链表的每个结点里再增加一个指向其前驱的指针域prior。这样形成的链表中就有两条方向不同的链,我们可称之为双(向)链表(Double Linked List)。所以本文主要讨论的是双向循环链表基本操作,包括创建、删除、插入、打印等原创 2015-06-18 21:19:23 · 1588 阅读 · 0 评论 -
算法学习之数组元素查找
【摘要】最近两个月都在学习 Linux 驱动,中间碰到了很多问题,进度比较缓慢。尽管不是班科出生的,但是还是觉得算法很有必要学一学。因此将数组元素查找作为自己算法开篇的第一篇博客,好好跟着平凡程序员的博客学习,内容基本是拿来主义。我们可以下面一个数组查找的函数说起。一句一句写起,首先我们开始从最简单的函数构造开始int find(int array[], int length, int value){ int index = 0; return index;} 这里看到,查找函数只是一个原创 2015-06-17 16:08:20 · 796 阅读 · 1 评论 -
数据结构学习之链表(单向、单循环以及双向)(递归实现)
本文主要讲的是各种链表的基本操作,包括单向链表、单向循环链表以及双向链表。主要是关于链表的创建、删除、插入、打印数据。基本操作的实现是通过递归来实现的。原创 2015-06-18 10:31:01 · 2153 阅读 · 1 评论 -
数据结构学习之单向链表的基本操作(非递归实现)
【摘要】本文讨论的均为带头结点的线性链表的基本操作,包括创建、删除、插入、打印等等,欢迎大家批评指正错误。(1)单链表存储结构typedef struct LNode{ int data; struct LNode *next;}LinkList;(2)创建链表/* 功能:构建一个空的带头节点的单链表*/Status InitList (struct LNode **L)原创 2015-06-18 20:35:53 · 1077 阅读 · 0 评论 -
数据结构学习之二叉树(性质总结)
1、二叉树结点编号在一棵n个结点的完全二叉树中,从树根起,自上层到下层,每层从左至右,给所有结点编号,能得到一个反映整个二叉树结构的线性序列。 编号特点 2、二叉树性质原创 2015-06-22 10:13:49 · 4791 阅读 · 0 评论 -
数据结构学习之队列(链式存储)
【摘要】前一篇博客主要讨论循环队列,但是循环队列都是事先申请好空间,使用期间是不能释放的。但是链队列,每次都可以进行申请和释放结点。再无法预估队列长度的时候,我们可以考虑用链队列。 (1)设计队列数据结构/*结点结构*/typedef struct _QUEUE_NODE{ int pData; struct _QUEUE_NODE *next;}QUEUE_NODE,*Q原创 2015-06-19 17:18:30 · 817 阅读 · 0 评论 -
算法学习之链表反转
【摘要】链表逆转是面试环境中经常遇到的一道题目,也是我们在实际开发中可能会遇到的开发需求。和线性逆转不一样,单向链表的节点需要一个一个进行处理。有需要的朋友可以看一下,如果有没考虑周全的地方欢迎指正。为了显示两者之间的区别,我们分别对线性内存和链表进行逆转:(1)连续内存数据反转STATUS normal_revert(int array[], int length){ int* pDat原创 2015-06-20 12:33:16 · 1846 阅读 · 0 评论 -
数据结构学习之二叉树(面试易考题整理)
【摘要】计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。二叉树是递归定义的,因此,与二叉树有关的题目基本都可以用递归思想解决,当然有些题目非递归解法也应该掌握,如非递归遍历节点等等。本文努力对二叉树相关题目做一个较全的整理总结,希望对找工作的同学有所帮助。二叉树原创 2015-06-23 09:20:56 · 7991 阅读 · 3 评论 -
Compare And Swap(CAS)实现无锁多生产者
struct node{struct node *next;int data;}struct node *queue;//队列头多个消费者(多线程)都需要向这个queue插入数据 为了说明问题的复杂性,先看看只有一个消费者时的情况,插入队列的操作非常简单: Step1) new_head->next = queue->head; Step2) queue->head = n原创 2015-07-27 21:59:22 · 3966 阅读 · 0 评论 -
OJ 系列之【中级】双链表基本操作
#include <stdlib.h>#define null 0#define MAXSIZE 50struct strlnode { int data; struct strlnode *plast; struct strlnode *pnext;};void create(struct strlnode **p, int x) /*创建双链表(表头节点)*/{原创 2016-02-22 10:38:10 · 907 阅读 · 1 评论