以下是高德纳在他的著作《计算机程序设计艺术》里对算法的特征归纳:
输入:一个算法必须有零个或以上输入量。
输出:一个算法应有一个或以上输出量,输出量是算法计算的结果。
明确性:算法的描述必须无歧义,以保证算法的实际执行结果是精确地匹配要求或期望,通常要求实际运行结果是确定的。
有限性:依据图灵的定义,一个算法是能够被任何图灵完备系统模拟的一串运算,而图灵机只有有限个状态、有限个输入符号和有限个转移函数(指令)。而一些定义更规定算法必须在有限个步骤内完成任务。
有效性:又称可行性。能够实现,算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现。
数据结构:
一般来说是这样的:
1、我们要解决一个跟数据相关的问题
2、分析这个问题,相处对应的数据结构
3、分析数据结构,先出算法
数据结构和算法是互相依存、不可分开的
你学习完排序算法,就能了解常见的数据结构
大分类
- 分治法:把一个问题区分互相独立的多个部分分别求解的思路。这种求解思路带来的好处之一是标语进行并行计算。
- 动态规划法:当问题的整体最优解就是由局部最优解组成的时候,经常采用的一种方法。
- 贪婪算法:常见的近似求解思路。当问题的整体最优解不是(或无法证明是)由局部最优解组成,且对解的最优性没有要求的时候,可以采用的一种方法。
- 现行规划法:见词条。
- 简并法:把一个问题通过逻辑或数学退了,简化成与之等价或近似的、相对简单的模型,进而求解的方法。
- 前端主要是用分治法——分而治之。
排序可视化:https://visualgo.net/bn/sorting
一些名词:
hash:指的是以key:value形式表示的数据结构
队列:
用一个数组举例, 数组的本质是一个hash。但是队列和栈的概念并不是指只有数组能实现。
张三先进来,李四进来,王五再进来。实际上就是排队,张三第一,李四第二,王五第三,再往后就没有了。先进先出
例如:12306的排队系统
栈:
与队列相反,先进的人后出。
例如:进电梯、盗梦空间
链表:
例如:
声明三个变量a1、a2、a3。a1的next为a2,当我们要删除value:2时,就将变量a1中next的值指为a3
两个概念:
第一个hash对象叫做head,这里也就是指的a1。
其它的都叫做节点:node
树(tree)
dom树
概念:层数、深度、节点个数、二叉树。
最后一个节点叫做叶子节点,因为叶子上面不会再长叶子。也叫断子绝孙节点(meta1、meta2、meta3)
二叉树:每次最多分两个叉的才叫二叉树
满二叉树:叶子长满的,也就是说二叉树叶子节点都是两个,通常分支被称为左子树右子树
完全二叉树:除最后一层外,其余层都是满的,并最后一层或是满的或者是在右边缺少若干个连续节点
完全二叉树(下图):
堆:
一个条件:爸爸的数字大于儿子的数字就叫堆
结论:
算法的优化只能从两点考虑
1:内存空间(桶)
2:算力(CPU)
例如:
计数排序:节约算力浪费空间
桶排序:节约空间浪费算力
冒泡排序流程图及伪代码:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
a <- {
'0':4,
'1':6,
'2':3,
'3':2,
'4':1,
'length': 5
}
轮数 = 1
while(轮数 < a['length'])
下标 = 0
while(下标 <= a['length'] - 1 - 轮数)
if a[下标] < a[下标+1]
else
t <- a[下标]
a[下标] <- a[下标+1]
a[下标+1] <- t
end
下标 <- 下标+1
end
轮数 <- 轮数 + 1
end
print a
插入排序流程图及伪代码:
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 以此类推,直到所有元素均排序完毕。
a<-{
'0'=4,
'1'=6,
'2'=3,
'3'=2,
'4'=1,
'length'=5
}
轮数=1
while(轮数<a['length'])
min下标<-轮数-1;左标<-min下标+1
while(下标<a['length'])
if a[下标]<a[min下标]
a[min下标]<-a[下标]
else
什么也不做
end
下标<-下标+1
end
t<-a[轮数-1]
a[轮数-1]<-a[min下标]
a[min下标]<-t
轮数<-轮数+1
end
print a
计数排序流程图及伪代码:
- 首先先入名字为hash的对象桶里,入桶时对其进行类似收扑克牌的排序。
- 数字是几就放在hash桶对应下标的第几位,标记为1,有重复的数字+1。
- 然后出桶,按照在hash对象里的排列顺序存入一个新数组,排序完成。
a <- {
'0':0,
'1':2,
'2':1,
'3':56,
'4':4,
'5':67,
'6':3,
'length:7'
}
hash <- {}
index <- 0
while index < a['length']
number <- a[index]
if hash[number] == undefined // hash[number] 不存在
hash[number] = 1
else
hash[number] <- hash[number] + 1
end
index <- index + 1
end
index2 <- 0
max <- findMax(a) // 最大值67
newArr <- {}
while index2 < max + 1
count <- hash[index2]
if count != undefined // count 存在
countIndex <- 0
while countIndex < count
newArr.push(index2)
countIndex <- countIndex + 1
end
end
index2 <- index2 + 1
end
print newArr