上一页 1 ··· 3 4 5 6 7 8 9 下一页
摘要: 摘要 书中第10章10.4小节介绍了有根树,简单介绍了二叉树和分支数目无限制的有根树的存储结构,而没有关于二叉树的遍历过程。为此对二叉树做个简单的总结,介绍一下二叉树基本概念、性质、二叉树的存储结构和遍历过程,主要包括先根遍历、中根遍历、后根遍历和层次遍历。1、二叉树的定义 二叉树(Binary Tree)是一种特殊的树型结构,每个节点至多有两棵子树,且二叉树的子树有左右之分,次序不能颠倒。 由定义可知,二叉树中不存在度(结点拥有的子树数目)大于2的节点。二叉树形状如下下图所示:2、二叉树的性质(1)在二叉树中的第i层上至多有2^(i-1)个结点(i>=1)。备注:^表示此方(2)深度为 阅读全文
posted @ 2013-01-27 12:02 Rabbit_Dale 阅读(4543) 评论(2) 推荐(2) 编辑
摘要: 摘要 本章介绍了几种基本的数据结构,包括栈、队列、链表以及有根树,讨论了使用指针的简单数据结构来表示动态集合。本章的内容对于学过数据结构的人来说,没有什么难处,简单的总结一下。1、栈和队列 栈和队列都是动态集合,元素的出入是规定好的。栈规定元素是先进后出(FILO),队列规定元素是先进先出(FIFO)。栈和队列的实现可以采用数组和链表进行实现。在标准模块库STL中有具体的应用,可以参考http://www.cplusplus.com/reference/。 栈的基本操作包括入栈push和出栈pop,栈有一个栈顶指针top,指向最新如栈的元素,入栈和出栈操作操作都是从栈顶端进行的。 队列... 阅读全文
posted @ 2013-01-26 17:39 Rabbit_Dale 阅读(2923) 评论(9) 推荐(1) 编辑
摘要: 摘要: 本章所讨论的问题是在一个由n个不同数值构成的集合中选择第i个顺序统计量问题。主要讲的内容是如何在线性时间内O(n)时间内在集合S中选择第i小的元素,最基本的是选择集合的最大值和最小值。一般情况下选择的元素是随机的,最大值和最小值是特殊情况,书中重点介绍了如何采用分治算法来实现选择第i小的元素,并借助中位数进行优化处理,保证最坏保证运行时间是线性的O(n)。1、基本概念 顺序统计量:在一个由n个元素组成的集合中,第i个顺序统计量是值该集合中第i小的元素。例如最小值是第1个顺序统计量,最大值是第n个顺序统计量。 中位数:一般来说,中位数是指它所在集合的“中间元素”,当n为奇数时,中位数.. 阅读全文
posted @ 2013-01-25 21:59 Rabbit_Dale 阅读(11334) 评论(5) 推荐(4) 编辑
摘要: 摘要: 本章先回顾了前面介绍的合并排序、堆排序和快速排序的特点及运行运行时间。合并排序和堆排序在最坏情况下达到O(nlgn),而快速排序最坏情况下达到O(n^2),平均情况下达到O(nlgn),因此合并排序和堆排序是渐进最优的。这些排序在执行过程中各元素的次序基于输入元素间的比较,称这种算法为比较排序。接下来介绍了用决策树的概念及如何用决策树确定排序算法时间的下界,最后讨论三种线性时间运行的算法:计数排序、基数排序和桶排序。这些算法在执行过程中不需要比较元素来确定排序的顺序,这些算法都是稳定的。1、决策树模型 在比较排序算法中,用比较操作来确定输入序列<a1,a2,......,a3&g 阅读全文
posted @ 2013-01-25 11:56 Rabbit_Dale 阅读(2110) 评论(3) 推荐(1) 编辑
摘要: 本章介绍了快速排序及其算法分析,快速排序采用的是分治算法思想,对包含n个数的输入数组,最坏情况下运行时间为θ(n^2),但是平均性能相当好,期望的运行时间为θ(nlgn)。另外快速排序能够就地排序(我理解是不需要引入额外的辅助空间,每次划分能确定一个元素的具体位置),在虚拟环境中能很好的工作。1、快速排序的描述 快速排序算法采用的分治算法,因此对一个子数组A[p…r]进行快速排序的三个步骤为: (1)分解:数组A[p...r]被划分为两个(可能为空)子数组A[p...q-1]和A[q+1...r],给定一个枢轴,使得A[p...q-1]中的每个元素小于等于A[q],A[q+1...r]... 阅读全文
posted @ 2013-01-24 16:28 Rabbit_Dale 阅读(4900) 评论(4) 推荐(0) 编辑
摘要: 《算法导论》第六章主要内容是关于堆和优先级队列,书中给出了一个练习题,非常有有意思,今天好好研究练习一下。题目如下:请给出一个时间为O(nlgk)、用来将k个已排序链表合并为一个排序链表的算法。此处n为所有输入链表中元素的总数。(提示:用一个最小堆来做k路合并)。 看到题目第个想到的是归并排序过程中的归并操作子过程,从头开始两两比较,找出最小的,然后接着往后比较,常用的是2路归并。而题目给的是k个已排好序的链表(k>=2)。如果没有提示,我半天不知道如何去实现,幸好提示说用最小堆来做k路合并,于是我想到可以这样做:创建一个大小为k的数组,将k个链表中的第一个元素依次存放到数组中,然后将数 阅读全文
posted @ 2013-01-24 11:23 Rabbit_Dale 阅读(3750) 评论(1) 推荐(1) 编辑
摘要: 1、概述 队列是一种满足先进先出(FIFO)的数据结构,数据从队列头部取出,新的数据从队列尾部插入,数据之间是平等的,不存在优先级的。这个就类似于普通老百姓到火车站排队买票,先来的先买票,每个人之间是平等的,不存在优先的权利,整个过程是固定不变的。而优先级队列可以理解为在队列的基础上给每个数据赋一个权值,代表数据的优先级。与队列类似,优先级队列也是从头部取出数据,从尾部插入数据,但是这个过程根据数据的优先级而变化的,总是优先级高的先出来,所以不一定是先进先出的。这个过就类似于买火车票时候军人比普通人优先买,虽然军人来的晚,但是军人的优先级比普通人高,总是能够先买到票。通常优先级队列用在操作系. 阅读全文
posted @ 2013-01-23 21:55 Rabbit_Dale 阅读(3904) 评论(3) 推荐(1) 编辑
摘要: 本章开始介绍了堆的基本概念,然后引入最大堆和最小堆的概念。全章采用最大堆来介绍堆的操作,两个重要的操作是调整最大堆和创建最大堆,接着着两个操作引进了堆排序,最后介绍了采用堆实现优先级队列。1、堆 堆给人的感觉是一个二叉树,但是其本质是一种数组对象,因为对堆进行操作的时候将堆视为一颗完全二叉树,树种每个节点与数组中的存放该节点值的那个元素对应。所以堆又称为二叉堆,堆与完全二叉树的对应关系如下图所示: 通常给定节点i,可以根据其在数组中的位置求出该节点的父亲节点、左右孩子节点,这三个过程一般采用宏或者内联函数实现。书上介绍的时候,数组的下标是从1开始的,所有可到:PARENT(i)=i/2... 阅读全文
posted @ 2013-01-23 16:43 Rabbit_Dale 阅读(11572) 评论(10) 推荐(3) 编辑
摘要: 本章介绍了算法分析中的渐进分析符号,几个重要渐进记号的定义如下:Θ(g(n))={ f(n): 存在正常数c1,c2和n0,使对所有的n>=n0,有0<=c1g(n)<=f(n)<=c2g(n) }O(g(n))={ f(n): 存在正常数c和n0,使对所有n>=n0,有0<=f(n)<=cg(n) }Ω(g(n))={ f(n): 存在正常数c和n0,使对所有n>=n0,有0<=cg(n)<=f(n) }o(g(n))={ f(n): 对任意正常数c,存在常数n0>0,使对所有的n>=n0,有0<=f(n)< 阅读全文
posted @ 2013-01-22 22:38 Rabbit_Dale 阅读(1705) 评论(0) 推荐(0) 编辑
摘要: 本章通过介绍插入排序和归并排序两种常见的排序算法来说明算法的过程及算法分析,在介绍归并排序算法过程中引入了分治(divide-and-conquer)算法策略。1、插入排序 输入:n个数(a1,a2,a3,...,an) 输出:输入序列的一个排列(a1',a2',a3',...an')使得(a1'≤a2'≤a3'≤...≤an')。 插入排序的基本思想是:将第i个元素插入到前面i-1个已经有序的元素中。具体实现是从第2个元素开始(因为1个元素是有序的),将第2个元素插入到前面的1个元素中,构成两个有序的序列,然后从第3个元素开始, 阅读全文
posted @ 2013-01-22 11:20 Rabbit_Dale 阅读(4483) 评论(6) 推荐(1) 编辑
摘要: 本章是本书的开篇,介绍了什么是算法,为什么要学习算法,算法在计算机中的地位及作用。 算法(algorithm)简单来说就是定义良好的计算机过程,它取一个或一组值作为输入,并产生出一个或一组值作为输出。即算法就是一系列的计算步骤,用来将输入数据转换成输出数据。 书中有一句话非常好: Having a solid base of algorithm knowledge and technique is one characteristic that separates the truly skilled programmers from the novices. 是否具有扎实的算法知识... 阅读全文
posted @ 2013-01-22 10:29 Rabbit_Dale 阅读(2527) 评论(3) 推荐(2) 编辑
摘要: 对于我们学计算机的来说,算法是程序员的内功,需要时间去练习。我还有大半年毕业,趁着在学校的时光,利用时间修炼内功。看《算法导论》是一个非常艰苦的过程,需要思考,练习。尤其是对我将要毕业的人来说,大环境下大家都去准备什么毕业旅游之类,尽情的去玩。玩是肯定要玩的,我想在玩的这段时间中也能学到知识。要耐得住寂寞,享受看书编程的乐趣。打下坚实的基础,为以后做好铺垫。 阅读全文
posted @ 2013-01-22 10:18 Rabbit_Dale 阅读(1120) 评论(1) 推荐(1) 编辑
摘要: 1、概述 系统调用mmap通过映射一个普通文件实现共享内存。System V 则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信。也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件。执行过程是先调用shmget,再调用shmat。对于每个共享的内存区,内核维护如下的信息结构,定义在<sys/shm.h>头文件中。 1 struct shmid_ds { 2 struct ipc_perm shm_perm; /* operation perms */ 3 int shm_segsz; /* size of segment (byte... 阅读全文
posted @ 2013-01-20 11:07 Rabbit_Dale 阅读(3527) 评论(0) 推荐(0) 编辑
摘要: 1、概述 Posix提供了两种在无亲缘关系进程间共享内存区的方法:(1)内存映射文件:先有open函数打开,然后调用mmap函数把得到的描述符映射到当前进程地址空间中的一个文件(上一篇笔记所用到的就是)。(2)共享内存区对象:先有shm_open打开一个Posix IPC名字(也可以是文件系统中的一个路径名),然后调用mmap将返回的描述符映射到当前进程的地址空间。者两种方法多需要调用mmap,差别在于作为mmap的参数之一的描述符的获取手段。2、Posix共享内存区对象 Posix共享内存区涉及以下两个步骤要求:(1)指定一个名字参数调用shm_open,以创建一个新的共享内存区对象或打开. 阅读全文
posted @ 2013-01-19 15:59 Rabbit_Dale 阅读(3637) 评论(0) 推荐(0) 编辑
摘要: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量... 阅读全文
posted @ 2013-01-16 15:08 Rabbit_Dale 阅读(3476) 评论(2) 推荐(0) 编辑
摘要: System V 信号量在内核中维护,其中包括二值信号量 、计数信号量、计数信号量集。二值信号量 : 其值只有0、1 两种选择,0表示资源被锁,1表示资源可用;计数信号量:其值在0 和某个限定值之间,不限定资源数只在0 1 之间;计数信号量集 :多个信号量的集合组成信号量集内核维护的信号量集结构信息如下:定义在头文件<sys/sem.h>struct semid_ds { struct ipc_perm sem_perm; struct sem *sem_base; ushort sem_nsems;... 阅读全文
posted @ 2013-01-14 10:55 Rabbit_Dale 阅读(4620) 评论(0) 推荐(1) 编辑
摘要: 1、概述 信号量(semaphore)是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语。信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。Posix信号量分为有名信号量和无名信号量(也叫基于内存的信号量)。2、Posix有名信号量 有名信号量既可以用于线程间的同步也可以用于进程间的同步。1)由sem_open来创建一个新的信号量或打开一个已存在的信号量。其格式为:sem_t *sem_open(const char *.. 阅读全文
posted @ 2013-01-13 19:39 Rabbit_Dale 阅读(4758) 评论(0) 推荐(3) 编辑
摘要: 1、概述 记录锁是读写锁的一种扩展类型,可用于亲缘关系或无亲缘关系的进程之间共享某个文件的读与写。被锁住的文件通过文件描述符进行访问,执行上锁的操作函数是fcntl,这种类型的锁通常在内核中维护。 记录锁的功能是:一个进程正在读或修改文件的某个部分时,可以阻止其他进程修改同一文件区,即其锁定的是文件的一个区域或整个文件。记录锁有两种类型:共享读锁,独占写锁。基本规则是:多个进程在一个给定的字节上可以有一把共享的读锁,但在一个给定字节上的写锁只能有一个进程独用。即:如果在一个给定的字节上已经有一把读或多把读锁,则不能在该字节上再加写锁;如果在一个字节上已经有一把独占性的写锁,则不能再对它加任.. 阅读全文
posted @ 2013-01-11 12:02 Rabbit_Dale 阅读(2684) 评论(0) 推荐(1) 编辑
摘要: 1、概述 读写锁与互斥量类似,不过读写锁允许更高的并行性。互斥量要么是锁住状态,要么是不加锁状态,而且一次只有一个线程对其加锁。读写锁可以有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可用同时占有读模式的读写锁。读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的,当它以写模式锁住时,它是以独占模式锁住的。2、读写锁API 读写锁的数据类型为pthread_rwlock_t。如果这个类型的某个变量是静态分配的,那么可通过给它赋常值PTHREAD_RWLOCK_INITIALIZER来初始化它。获取和释放读... 阅读全文
posted @ 2013-01-09 16:17 Rabbit_Dale 阅读(4689) 评论(1) 推荐(1) 编辑
摘要: 为了允许在线程或进程之间共享数据,同步时必须的,互斥锁和条件变量是同步的基本组成部分。1、互斥锁 互斥锁是用来保护临界区资源,实际上保护的是临界区中被操纵的数据,互斥锁通常用于保护由多个线程或多进程分享的共享数据。一般是一些可供线程间使用的全局变量,来达到线程同步的目的,即保证任何时刻只有一个线程或进程在执行其中的代码。一般加锁的轮廓如下:pthread_mutex_lock()临界区pthread_mutex_unlock()互斥锁APIpthread_mutex_lock(pthread_mutex_t *mutex);用此函数加锁时,如果mutex已经被锁住,当前尝试加锁的线程就会... 阅读全文
posted @ 2013-01-09 10:49 Rabbit_Dale 阅读(10706) 评论(3) 推荐(4) 编辑
上一页 1 ··· 3 4 5 6 7 8 9 下一页