读<算法图解><笔记摘录>

从很多途径当中,看到过这本书的知识点,是一本很有趣的算法入门书籍,最近花费了几天的时间将其阅读完,总想着总结一下这本书的算法知识点,分享给大家,也让自己掌握地更加踏实一点.

算法:一组完成任何任务的指令

算法这玩意,在保证满足条件,并且不浪费内存的情况下,要尽可能速度更快,这就是我们要使用和选择算法的原因.
在这本书当中称为运行时间,在下面每一种算法的过程当中都尽可能会涉及到.

二分查找在这里插入图片描述

二分查找的对象是一组有序的数组,记住必须是有序的
在这组数组当中定义定义索引0是low,而索引(数组最大索引)为high
当low<=high的时候,mid=(low+high)/2
这里一看上面书籍就写错了
如果说中间索引对应的数值刚好等于我们要查找的数字
则直接返回中间索引数值就好了
否则判断中间索引对应的数值和我们要查找数字的大小关系
如果大于,则high=mid-1,相当于我们搜索low到mid-1这个范围
如果小于,则low=mid+1,相当于我们搜索mid+1到high这个范围
继续返回上面的while,迭代就行
如果运行结束,数组当中没有任何数值等于我们要查找的数值
则返回None
运行时间:
在这里插入图片描述
线性时间描述为O(n)
二分查找的运行时间描述为O(logn)
//O(n*logn)这样的算法包括快速排序—一种较快的排序算法
//O(sqrt(n)),这样的算法包括将介绍的选择排序----一种速度较慢的排序算法
O(n!)这样的算法包括将介绍的旅行商的解方案—一种速度非常慢的算法<不建议去看和使用>—正常情况下用不到的
ex:大O表示法是一种特殊的表示法,指出了算法的速度有多快.
图例如下:
在这里插入图片描述
把纵坐标想成时间,去看这几个图就行了

选择排序

需要将数据存储到内存时,你请求计算机提供存储空间,计算机给你一个存储地址。需要存储多项数据时,有两种基本方式——数组和链表。

ex:数组的读取速度很快,但是链表的插入和删除速度很快.
ex:在同一个数组当中,所有元素的类型都必须是相同的

使用数组意味着事项在内存当中都是相互连接的,或者说紧靠在一起的
同时数组的好处在于可以挑选出其中的任何一个事项目,例如a[1]或者a[10],可以直接输出.
但数组的插入和删除是相当麻烦的,例如一个a[5]的数组,存储有5个数据,如果删除掉开头或者结尾的数据,还比较简单,但是如果删除掉中间的数据,例如a[3],就需要将原来的a[4]和a[5]同时提前,插入同样复杂.

而链表中的元素可以存储在内存的任何敌方,不需要相互连接或者紧靠,但链表的每个元素都存储了下一个元素的地址
链表无法像数组那样可以直接挑选出,其中任何一个事项的数据,必须从头开始串联,一直到所寻找的数据为止.
链表的插入和删除相对简单,例如5个数据,我需要删除第3个数据,则只需要使得第二个数据的下一个地址为第四个数据.原来的第三个数据自动删除

选择排序:
在这里插入图片描述
就是数组从头到尾,依次比较大小,每次都找出数组当中最大或者最小的数据放在数组的一端进行存储,直到全部循环完毕.
如果是二维数组,是不是让我们想起来了冒泡法:

    //采用冒泡排序法
    for(j=1;j<i;j++)
    {
        for(k=0;k<i-j;k++)//从第一个数开始,一直到倒数第二个数,比较大小
        //然后是第一个数开始,一直到倒数第三个数,比较大小,依次
        {
            if(a[k+1]<a[k])
            {
                temp=a[k];
                a[k]=a[k+1];
                a[k+1]=temp;
            }
        }
}

递归

递归总而言之就是一种分而治之的策略
盒子里面找盒子,直到找到盒子里面的钥匙为止.
或者说递归指的就是调用自己的函数
在这里插入图片描述
在这里插入图片描述
第一种方案是递归,而第二种方案则是循环.
ex:使用循环的性能更好,但是如果使用递归,程序更加容易理解.
递归函数当中有两个条件,一个是基线条件,一个是递归条件,递归条件很容易理解,就是持续循环,那什么时候判断循环结束呢?这个就叫做基线条件
ex:调用栈
举例说明栈这个基本概念:一叠便条要简单很多,插入的待办事项放在清单的最前面;读取待办事项时,你只读取最上面的那个,并将其删除.也就是先进后出.
因此这个代办事项清单只有两种操作:压入(插入)和弹出(删除并读取)
在这里插入图片描述
ex:调用栈,每个函数都需要占用一定的内存,这将导致运行速度变慢.可以转换为循环重新编写代码.或者使用尾递归<这里不做说明>

快速排序

一种优雅的排序算法

//第一种方法,采用快速排序的方法

int cmp_int(const void* _a,const void* _b)
{
    int* a=(int*)_a; //强制类型转换
    int* b=(int*)_b;
    return *a - *b; //从小到大进行排序,升序,如果是降序,则修改为*b - *a;
}
    qsort(a,n,sizeof(a[0]),cmp_int);

是一种分开来治理的算法,可以直接使用
在这里插入图片描述

散列表

简单说,就是存储数组索引的一组代号
散列表非常适合于防止重复
思考一下,投票的时候,我们无法控制每个人只投了一票,所以我们可以采用散列表将每个人的姓名进行存储,如果出现重复的则进行条件处理.
例如:
在这里插入图片描述
上图如果无法理解,想一想手机的通讯录,里面有联系人和电话号码.我们不可能记住每一个人的电话号码,但是我们知道要给谁打电话,而通讯录里面的用户名就是散列表
在这里插入图片描述
要注意使用散列表的时候,尽可能避免冲突和保持性能:
1.较低的填装因子<=0.7
在这里插入图片描述
2.良好的散列函数

广度优先搜索

BFS算法:适合回答"到X的最短路径是什么,或者说到X是否存在路径"这样的问题

在这里插入图片描述
从起点出发,一步可以到达的地方进行存储
二步可以到达的地方进行存储
三步
四步
一直到"n步"数组当中存在有终点,则找到了从起点到终点最短路径为n

ex:队列,不同于栈,队列是一种先进先出的结构<入队和出队>
在这里插入图片描述
在这里插入图片描述
注意此处是先把第一关系的循环完,然后再执行第二关系循环.
ex:一个人可能即是a的朋友又是b的朋友,那么我们将产生重复,为避免这种情况,我们需要调用一个检查函数,如果已经执行过,则进行标记.
在这里插入图片描述
运行时间:,广度优先搜索的运行时间为O(人数 + 边数),这通常写作O(V + E),其中V为顶点(vertice)数,E为边数。
无法往后指的图叫做树,例如族谱
在这里插入图片描述

狄克斯特拉<后续我将提供一道QT,供大家理解>

找到加权图中前往X的最短路径
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
如果有负权边,就不能使用狄克斯特拉算法。
在包含负权边的图中,要找出最短路径,可使用另一种算法——贝尔曼–福德算法

贪婪算法

NP完全问题,每一步直接找到最小的或者最大的,然后加起来就是全部最小的或者最大的
局部全部都小构成了全局尽可能小

动态规划

把原来数组和所要求的结果,构成一个新的数组,称为dp数组,然后找到最后一行或者第一行当中数据的最优解,则是我们要寻找的数据.

K最近邻算法

找案例A距离或者关系最近的另一个案例B,则B的特征可以代表案例A的特征.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值