贪心Greedy
一 概念
只看到眼前;苟且
关注的只是这个问题当下的一个局部,使它朝着你的目标使得最大化。
二 数据结构的基础
1 vector(数组)
查找的复杂度O(1),但是插入删除一个元素的复杂度很高;
线性结构(1:1)
2 list(列表)
查找慢,但是插入和删除元素快,与vector正好互补
线性结构(1:1)
3 stack(栈)
只能在栈顶进行插入删除和访问操作
先进后出
线性结构(1:1)
4 Queue(队列)
在队首队尾进行插入和删除和访问操作
先进先出
线性结构(1:1)
5 tree(树)
非线性结构(1:n)
树中研究的都是二叉树
6 Graph(图)
树是无环的
(1)Graph as matrix
(a)无向图
无向图的矩阵是对称矩阵
(b)有向图
(c)网格
边是有权重的,
(2)Graph as vector
用矩阵的形式会浪费很多的内存,所以优化成vector
只记录每一行中有效的部分
但是只查找的时候比较慢了
算法就是折中
三 排序
1 Gnomesort
这个算法很好的体现了贪心策略
这个算法概括为一句话就是:顺序往前走(i++);逆序往后走(i- -)
顺序往前走:
逆序往回走:
思考题:
if(i<1||s[i-1]<=s[i])
i++;
问题1:为啥要写个i<1,并且通过||链接起来。
问题2:可以交换两个条件的位置吗?将这两个条件换个位置会怎么样?
但是这个复杂度是O(n^2)
这个算法的改善:
记录下来位置,然后直接过去就可以了;
k是辅助记忆。
k在内循环中是不会被修改 的
下一次内循环的开始是直接从上次已经排号序的k开始,而不是从退回去的i的位置重新开始;但是 这个改善不是革命性的;也就只能变为O(n^2/2)
2 BubbleSort
这个算法也是贪心策略
气泡算法在有逆序发生的时候关注的是左边的元素,让它一步步的往前走;(前面的算法关注的是右边的元素,让它往左走)
这个算法总结一句话:每次找最大的放就位,直到海枯石烂
算法的复杂度是O(n^2)
(1)bubble基础版
发送了逆序:
第一次:
第二次
冒泡排序中每次一个流程都是将这个流程中最大的元素排到了最后;这个是怎么保证的呢?
如下图:冒泡排序中有每个窗口有两个元素,窗口每次的移动都会选两个元素中的最大的元素;随着窗口的不断移动这个序列中最大的元素就到了最后的位置了;直到最后一次流程结束的时候排序就做好了 !
其实在整个流程中真正起作用的是整个排列中最大的那个元素,一旦找到这个元素,它就会在 每次过程中与另外一个元素交换元素,直到最后;总而言之,每次的流程都会把当前排列中最大的元素送就位;
冒泡排序的整个效果图如下:
最大的元素不断的在就绪,没有排序好的元素整体都在排好序的元素的下方;
具体实现代码如下:
第二个函数就是上面所谓的窗口的代码化;(一次流程找到当前序列的最大值)
将第二个函数 放在第一个函数中的意思就是:将所有流程中的最大值就绪:每次找到一个最大值,hi都会相应的–
(2)bubble改进版
下面这个图其实只要第一个元素在第一次执行完一次流程后就排序做好了,但是按照基础版的算法的化还会进行n-2次,其实剩下的都是没有必要的,可以终止了;所以要提前终止;
这个算法就是通过提前终止来改善算法的;
如果一个流程在扫描完后,发现没有进行交换,那就证明是有序的了,可以结束这次 循环了;通过bubble函数的返回值来提前结束bubblesort函数
(3)再改进——跳过无效气泡
三 Matrix Sorting
随机的矩阵,先做列排序,再做行排序,。列还是排序好 的,没有改变
如何证明?
四 Huffman:PFC coding
Huffman树的过程:
每次都是先将森林中两个最小的树合并成一棵树,然后再按照大小排序,然后再合并,再排序 ,不断地重复最后得到一颗Huffman树,就得到了最优结果;
贪心的策略:每次都是局部的两棵最小的子树,唯一做的事情是把那两颗子树合并起来,把他们的权重加起来,再把它重新插回到森林中,周而复始,反反复复的迭代,直到最后变成一棵树
用01来表示字符;避免前缀的歧义
每个字符的比特是由叶子的深度决定的,下面三个方案,可以看到不同的编码方式,字符串的比特不同;如何是得一个字符串的比特最小,这格式huffman要解决的问题;下面图是没有权重(各个字母都是出现一次)的情况下:可以看到是满二叉树的时候是最小的时候;
当由了权重后(每个字母在字符串中出现的次数 不同的时候 ),满二叉树就不是最优的结果了;要得到最优的结果,Huffman在读博士的时候就用到了贪心策略,出现频率越高的字母放到树的最高处
从叶子开始增长,这棵树的增长只能是合并, 而不能是分割;
第一步:根据一段文字统计一下字母的频率
第二步:从叶子开始增长,这棵树的增长只能是合并, 而不能是分割;
把叶子合成子树,然后再把子树合成更大的子树,直到最终合成一颗完整的树
把出现频率最高的元素放到最高,
把最小的两个合并成一棵树,整个过程中出现了森林;
将新合成的树插到相应的 位置 上;
每合并一次森林里 的树就会少一颗,从而会越来越少,最后合成一颗树
完工:这就是Huffman用贪心策略得到的Huffman树
每次都是先将森林中两个最小的树合并成一棵树,然后再按照大小排序,然后再合并,再排序 ,不断地重复最后得到一颗Huffman树,就得到了最优结果;