数据结构与算法学习笔记
文章平均质量分 78
thefutureisour
ZTE基带部码农,平时工作很忙,不再更新opencv相关内容,也不解答大家问题了。
展开
-
队列的简单应用-杨辉三角和约瑟夫环
接上一篇,由于队列的内容相对比较简单,所以这次举两个实际的问题—杨辉三角和约瑟夫环。(不知道这两个问题的童鞋可以自行百度。)先看杨辉三角。使用队列解决这个问题有1个小的技巧:第一就是在两个1的两边增加两个0,通过0来标记这一层的结束。先看程序吧://遍历循环链表并打印void printQueue(Queue *q){ for(int i = 0; i < Qlength(q);++原创 2012-08-06 22:32:34 · 2679 阅读 · 1 评论 -
哈希表
哈希表,又称为散列,是一种更加快捷的查找技术。我们之前的查找,都是这样一种思路:集合中拿出来一个元素,看看是否与我们要找的相等,如果不等,缩小范围,继续查找。而哈希表是完全另外一种思路:当我知道key值以后,我就可以直接计算出这个元素在集合中的位置,根本不需要一次又一次的查找!是不是很神奇呢?其实一点也不神奇,举一个例子就明白了,假如我的数组A中,第i个元素里面装的key就是i,那么数字3肯定是在原创 2012-09-03 15:09:05 · 960 阅读 · 0 评论 -
求图的最小生成树
上一小节讨论了一些图的基本概念。其中提到,如果有两幅图G=(V,E),G'=(V',E'),如果V'∈V,E'∈E,则称G'是G的子图。如果V'=V,且E'∈E(即顶点不少,边少了几条),那么G'是G的生成子图。特别的,如果生成子图是一棵树,即满足定点数 = 边树+1,那么这棵树称为生成树。最小生成树的概念是基于“带权图”的。即图中每条边上都有特定的权值,这样的图又称为网。最小生成树指的是所有原创 2012-08-25 11:22:02 · 8297 阅读 · 2 评论 -
排序算法3-堆排序与优先队列
首先说明一点,不要被名字所误导,优先队列并不是一种排序饿算法,而是一种数据结构。这个结构与一般的先入先出的队列不同,它每次出队的是优先级最大的元素。当一个指定优先级的元素入队时,能够很快的把它排到队列中。把这两个放在一起,是因为优先队列是用堆排序的方法设计的。首先先看堆排序吧。堆是一个完全二叉树。完全二叉树我们之前已提过,就是它的前面是满的,直到最后一层除外。最后一层从左边起一直都有叶子,但是原创 2012-09-03 21:26:44 · 4407 阅读 · 0 评论 -
最短路径与Dijkstra算法
给定一个有向图G和起点S,如何求出图中S到其中所有点的最短路径呢?Dijkstra给出了一个比较好的算法,它的基本步骤如下:1.计算起点s到所有节点的距离。2.挑出其中距离最小的节点smin。(如果这个节点已经被调过了,就不再选它了)3.利用这个节点更新起点到其他节点的最小距离:如果s到smin的直接距离+smin到其他节点某个节点的直接距离 4.不断重复2、3直到只剩下一个节点。原创 2012-08-28 08:22:13 · 908 阅读 · 0 评论 -
关键路径
关键路径问题也是从实际中抽象出来的,他解决的是这么一类的问题:加入我们完成一件事需要6个工序,其中的一些该工序是可以并行进行的,另一些工序的顺序是有一定要求的,并且每道工序花费的时间并不一定相同。比如做完A才能做B或者C,花费的时间分别为3,2.做完B之后才能做E,花费的时间为3。做完C之后才能做F,花费的时间为3。B和C都做完才能做D,花费的时间分别为:2,4.C,D,E都做完之后才能做最后一件原创 2012-08-28 15:09:12 · 1653 阅读 · 0 评论 -
拓扑排序
简单的说,从某个集合上的一个偏序得到该集合上的一个全序,这个操作称为拓扑排序。偏序指得是这个集合中的仅有部分元素可以比较,而全序指的是集合的全体成员之间均可以比较。这种排序在生活中也很常见,比如上学期间学的课程:要学随机过程就必须学过概率论和高等数学,要学数值分析必须学过高等数学和线性代数,要学模电必须学过电路,等等。所以,假如课程很多的话,如何通过程序来求解一个合适的学习顺序呢?首先得通原创 2012-08-27 13:47:38 · 1094 阅读 · 0 评论 -
二叉树
这一小节我们介绍一种特殊的树—二叉树。它的特殊之处在于每个?根节点的叶子节点个数不超过两个,所以我们很容想到通过下面的结构定义二叉树:typedef char ElemType;typedef struct BTreeNode{ ElemType vaule; struct BTreeNode *Lchild; struct BTreeNode *Rchild;}BTreeNod原创 2012-08-17 10:55:34 · 1228 阅读 · 0 评论 -
图和图的遍历
由于本人没学过离散数学,在这里只能班门弄斧一下了:一幅图(graph)G = (V,E)是由顶点集V(vertex)和边集E(egge)组成的。每一条边就是一个点对(v,w),其中v,w∈V。如果点对是有序的,那么图就是有向的,否则成为无向图。如果两个顶点(v1,v2)∈E,那么它们就是相关联的,它们互为邻接点。一个点的度数,指的是与这个点相关联的顶点的个数。对于有向图,还分为入度和出度。如果原创 2012-08-24 13:40:52 · 1735 阅读 · 1 评论 -
树的定义及基本操作
首先,什么是树呢?数的定义是递归的:定义树是满足以下条件的,包含至少一个结点的有限集合:(1)树中有一个特别指定的结点,称为根,或树根。(2)其它结点划分成n>=0个不相交的集合T1…Tn ,每个集合又还是一棵树,但称为根的子树。树的主要操作包括:求树的深度、求给定节点的子节点、兄弟节点、遍历树、插入子树、删除子树等等。因为树的定义本身就是递归的,所以在实际的程序中,很多操作原创 2012-08-17 10:52:08 · 5522 阅读 · 0 评论 -
几种排序算法的比较
几种排序算法的比较:排序方法平均情况最好情况最坏情况辅助空间稳定性直接插入O(n^2)O(n)O(n^2)O(1)是希尔O(nlogn)~O(n^2)O(n^1.3)O转载 2012-10-12 23:31:38 · 1031 阅读 · 0 评论 -
排序算法1—插入排序、选择排序、冒泡排序
排序算法有很多,这里先按照算法的复杂程度由浅入深的介绍一些常用的排序算法。1.插入排序:这是一种非常直观的排序算法。它的基本思路就是:从数组的第二个元素开始,依次取数组中的元素,将它与前面的的元素相比较,插入到这个元素的前面或者后面(这取决于你想从大往小排序还是从小往大排序)。然后再取下一个元素,跟前两个已经有序的数比较,插入到合适的位置。依次类推。下面看一下程序://插入排序voi原创 2012-09-03 16:21:55 · 1346 阅读 · 0 评论 -
如何判断链表中是否有环
今天面试被问住了,很惭愧啊,回来上网查了一下思路。自己写了点程序。1.如何判断是否有环?如果有两个头结点指针,一个走的快,一个走的慢,那么若干步以后,快的指针总会超过慢的指针一圈。2.如何计算环的长度?第一次相遇(超一圈)时开始计数,第二次相遇时停止计数。3.如何判断环的入口点:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接原创 2012-11-12 16:04:08 · 52905 阅读 · 29 评论 -
队列
队列是从现实的“排队”现象中抽象出来的:新来的只能排在队伍的最后面,当你完成的自己事情,就可以离开队列,不能插队。队列是一种特殊的线性结构,它只能在这个结构的一端插入元素,在另一端删除元素。这两端分别称为队首和队尾。当我们一看到要频繁的插入、删除元素,第一反应就是中链表实现。的确,在原有链表的基础上,稍作改动,就能把它变成一个队列。但是,程序员们想出了一个更加巧妙地办法,利用数组,准确的说,是原创 2012-08-06 15:02:07 · 2176 阅读 · 2 评论 -
排序算法2-快速排序、归并排序
快速排序的思路是这样的:假如我从数组中挑出一个数(通常选为第一个数),那么我总可以利用这个数把数组分为两部分:大于这个数的部分和小于这个数的部分。然后对于这个两部分,分别重复前面的步骤,直到每一部分都只剩下2个数为止,我们可以比较出来。一看就知道是一个递归的程序,但是程序的难点在于:如何从用一个数把数组分为两个部分呢?当然。你大可以用一个比较笨的办法:搞一个临时数组,然后把比较的结果放在数组里原创 2012-09-03 16:56:57 · 929 阅读 · 0 评论 -
使用指针实现的线性表——链表
前一小节介绍使用数组实现了线性表,这一小节使用指针来实现:先看那12个函数:#include #include typedef int ElemType;typedef struct LNode{ //存放的数据 ElemType data; //指向下个节点的指针 LNode *next;}LNode,*LinkList;//初始化链表bool initL原创 2012-08-04 20:15:24 · 4244 阅读 · 3 评论 -
字符串
其实字符串就是一种更加特殊的线性结构。他表现在:1.使用char类型的数组来存储。2.面向字符串的操作与一般的顺序表不同,比如元素的插入、删除、确定位置等,一般的顺序表定义的操作都是1次处理一个元素,而字符串的操作往往是处理若干个字符。因为字符串操作的这些特殊性,所以C语言中专门在string.h头文件中定义了许多关于字符串的操作,其中比较重要的是:字符串输出函数 puts、字符串输入函数ge原创 2012-08-12 10:07:28 · 954 阅读 · 0 评论 -
利用线性表压缩稀疏矩阵
稀疏矩阵,就是矩阵中的大多数元素为0,只有少量的非0元素。对于这种矩阵,直接存储就有点浪费空间了,更好的办法就是定义一个结构体,结构体中的3个成员对应于非0元素的位置以及非0元素的值。然后在加上一些附加的信息,比如矩阵的大小、非0元素的个数等等。听起来挺简单的,但是写起来还是挺复杂的:#include #include #include //使用随机数调用#include //通过时原创 2012-08-13 13:31:49 · 1136 阅读 · 0 评论 -
数据结构-引言
说来惭愧,我是学通信专业的,没学过数据结构。虽然计算机二级考试的时候看过一点数据结构,但是考完试就忘了。在编程的过程中,逐步体会到了数据结构是多么重要,趁现在还比较年轻,打算仔细的学学。首先,数据结构是干什么的?为什么它总是跟算法扯上关系?概括的说,要用计算机求解实际问题需要做两件事:第一,把实际问题用计算语言描述;第二,用计算机语言求解这个问题。第一件事情是数据结构干的,第二件事情就是算法干原创 2012-07-27 18:14:19 · 1989 阅读 · 4 评论 -
重提循环队列
之前写过一篇博客介绍队列:http://blog.csdn.net/thefutureisour/article/details/7835273后来发现这个这个队列是有问题的:bool enQueue(Queue *q,ElemType e){ //如果队列已满,重新分配内存 if(q->rear == q->Qsize-1) { q->data = (ElemType*)re原创 2012-08-29 14:37:06 · 868 阅读 · 0 评论 -
静态查找
学完了3种数据结构(线性、树、图)之后,我们下面简要的介绍两大类算法:查找和排序。为什么介绍这两种算法呢?主要是因为这两种算法的应用实在是太广了,所以这里就单独拿出来讨论一下。查找算法可以分为两大类:静态查找和动态查找。静态查找,就是在查找的过程中不进行插入,删除等操作;反之就是动态查找。这也是与我们生活中的情况相对应的:如何一个学生去图书馆借书,他先得查图书馆里面有没有这本书,他做的事情原创 2012-08-29 15:16:57 · 1184 阅读 · 1 评论 -
利用树实现霍夫曼编码
昨天本来就把这篇文章发出来了,但是程序有一点小的问题,而且没有解码步骤,几天全部补上。霍夫曼编码是Huffman在MIT的博士毕业论文中提出的一种编码方法。因为它的简单实用,所以虽然已经过去了很多很多年,但这种方法依然经久不衰。说来惭愧,虽说是通信专业科班出身,但是信息论的内容已经忘得差不多了,只记住了如何编码,而这种编码背后所蕴含的复杂的数学推导(否则也不能作为博士论文发表啊),已经几乎没有原创 2012-08-21 09:23:53 · 3809 阅读 · 0 评论 -
动态查找—二叉排序树
动态查找的大多借助于树类型的结构,这里只介绍最简单的一种——二叉排序树。二叉排序树是这样一种树:它的要么是空的;如果它的左子树不为空,那么左子树上所有节点的值均小于根节点的值;如果右子树不为空,那么右子树上的值均大于根节点上的值,并且它的左右子树还是二叉排序树。二叉排序树有一个重要的性质:当你中序遍历该树时,得到的遍历结果是有序的。但这一切跟动态查找查找有什么关系呢?使用线性数据结构,也能原创 2012-08-30 16:38:51 · 3110 阅读 · 0 评论 -
递归操作简介
因为在树的内容中,要大量遇到递归的操作,所以着这里复习一下递归操作。递归,就是自己调用自己。首先,需要搞清楚函数是如何调用的。在执行被调函数之前,系统需要做3件事:1.将实参,函数的返回地址等信息传递给被调函数保存。2.为被掉函数的形参,局部变量分配空间3.将控制转移到被调函数入口。当从被调函数返回前,也需要做3件事:1.保存函数的返回结果2.释放被调函数存储空间原创 2012-08-16 17:04:56 · 2628 阅读 · 0 评论 -
用数组实现线性表
对于线性结构,有两种保存的方法,一种是使用C语言中内置的数组,这样的结构成为顺序表;另一种使用指针,这样的结构成为链表。对于线性结构,有12种基本的操作,分别是:初始化、删除、清空、判断是否为空、遍历、求表的长度、求某个元素在表中的位置、返回特定序号的元素、求某个元素的前一个元素、求某个元素的后一个元素、插入一个元素、删除一个元素。这一小节介绍如何利用数组实现线性表。先看程序:原创 2012-08-04 14:07:02 · 8824 阅读 · 3 评论 -
栈
栈也是线性结构的一种特例。与队列不同,他只有一个口,只能从这里读或者写数据,这个口称为栈顶(top)。栈是一种先进后出的数据结构。先进来的元素会放入栈底,而后进来的元素被放在它的上面,最后进来的元素的上面的位置,称为栈顶。栈所提供的操作比一般的线性表要少很多,只提供:初始化、销毁、判断是否为空、求栈的长度、清空栈、将数据压入栈、将数据弹出栈、或得栈顶元素这几种操作。其中将数据压入栈、将数据弹出原创 2012-08-07 14:02:53 · 1753 阅读 · 3 评论 -
链表逆置
这也是面试时常考的问题:pNode reverseList(pNode head){ pNode p1; pNode p2; pNode p3; //如果为空或者只有一个元素,直接返回 if(head == NULL || head->pNext == NULL) return head; p1 = head; p2 = head->pNext; while(p2)原创 2012-11-17 09:41:06 · 1363 阅读 · 1 评论