数据结构&贪心算法(一) by邓俊辉老师

前言
1、大O记号(Big-O)
消耗的资源越少越好。时间&空间越少越好。
先研究时间T(n):将常系数、低次项忽略。在这里插入图片描述
2、数据结构
线性结构
数组Array: A[n] A[0,n) 长度为n A[lo,hi) low-high 左闭右开 右减左即元素个数
向量vector:O(1)时间即可取出该元素、查找快;插入、删除元素慢 call by rank
接口:interface vector ~vector insert remove search
列表list:逻辑依然相连(link)、物理不相连 查找慢、插入删除元素快 call by position(后继succ、前驱pred)
栈stack:push、pop、top(栈顶)、FIFO 不能随意插入元素,仅能从一端读取(open的一端)
队queue:enqueue(插入rear尾部)、dequeue(取出front前端)用于cpu资源分配轮值服务、打印机并发使用等
半线性结构
树Tree : 域名 大部分树可以变为二叉树。无环
将树规范化:管理转变(父节点-子结点)
->(父节点-长子-次子) 对于任意一个节点只记两个关系 长子?,弟弟?
->再将长子和弟弟左右八字排(不再垂直水平)->二叉树(每一个节点两个孩子)。
在这里插入图片描述

图Graph: 无向图(undigraph)->矩阵描述 对称的是有冗余的
有向图(digraph)->矩阵描述 非对称的 无冗余的
有权图(network)->矩阵扩展。还要记录权重。
优化数据结构:
图化为矩阵。但零元素太多。将矩阵的零元素取出。每一行做一个list。
Graph as Vector 一列列标作为向量、每一行作为list。节省大量空间。
缺点不能快速查找,只能找vector入口,进入list注意查找

贪心 Greedy

排序

naiveGnomesort(S[],n){ //single loop but(O(n^2))
    for(int i = 1; i<n;;) //从第二个元素开始
    if( i<1 || S[i-1] <= S[i]) //GREEDY:目光只关注于当下相邻的两个元素
        i++; //inefficient backtracking 回溯
    else{
        swap(S[i-1],S[i]);
        i--; //逆序交换后往前走
    }
}

复杂度:以最坏的情况 worst case 考虑。从0依次加到n-1—> 即O(n^2)
最坏的情况完全逆序:最好的情况完全顺序。

加快一些,记录那个位置k。 但是bigO 不会变。

naiveGnomesort(S[],n) //still (O(n^2))
    for(int k = 1; k<n;k++) //nested loop 
        for(int i = k; 0 < i && S[i-1]>S[i];i--) //backtrack to k and rescan
            swap(S[i-1],S[i]);

Bubblesort冒泡排序
不变性:经过k趟扫描后,最大的k个元素必然就位
单调性:经过k趟扫描后,问题规模缩小至n-k
正确性:至多经过n趟扫描后,算法必然终止
基本版->提前终止版->跳跃版(部分有序)

template<typename T> \\ 基本版
void Vector<T>::bubbleSort(Rank lo, Rank hi){
	while(lo <  -- hi){
		for(Rank i = lo ; i < hi; i++ )
			if( _elem[i] > _elem[i+1] )    //逆序
				swap( _elem[i], _elem[i+1] ); //交换
	}
}
template<typename T> \\ 提前终止版
template <typename T>
void Vector<T>::bubbleSort(Rank lo, Rank hi){
    for( bool sorted = true; sorted = !sorted; )  \\ 注意循环判断条件
        for(Rank i = lo; i < hi-1; i++)
            if ( _elem[i] > _elem[i+1] )
                swap( _elem[i], _elem[i+1]),sorted = false;
}
在这里插入代码片

matrix sort 将一个矩阵排序、分别对他们先做逐列排序、再做逐行排序。
试说明列上依然是有序的尽管组成元素变了。
证明过程?
仅考虑两行即可,类似于bubblesort 其执行过程与输入没有关系 前后两个元素的位置是固定的

哈弗曼编码

Huffman :PFC Coding
“1 010 011 00”=“MAIN”
一个二叉树有n个叶子节点,有n-1非叶子节点(内部节点)。
树也是一种连通图
叶子节点(根节点)到另一节点(根节点)是唯一的。
利用左右对应01 左零右一(左孩子、右孩子)
编码解码的前提:这棵树双方都是约定好的。
在这里插入图片描述
注意不同的编码方案所需的字节比特数不同

Huffman:Unweighted Optimal 无权重的优化——满树(深度差不超过一)
每个字符的编码数取决于每一个的深度。
如何降低总深度:将深层次的节点与浅层次的节点做一个转换。(有两个叶子节点的深度相差两层,那么可以将深层次叶子节点的父节点与浅层次的叶子节点交换)
full-binary tree 深度差不超过一的二叉树–完美二叉树

Huffman:weighted optimal 有权重的优化
有权重的二叉树?不一定是完美二叉树才是最好的。
贪心原则:puting higher higher -->weighted optimal Huffman编码
把出现频率最高的字符(m)放在最上面(例如:“mammamia”)

哈弗曼树:先统计词频信息
从叶子节点开始向根的方向 构造树。
从出现频率最低的和作一个数。逐一寻找出现频率最低的两棵树、捏在一起。
和在一起的新树的权重相加就可以作为新的子树的权重。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值