算法和数据结构复习:稳定与非稳定排序、mysql的索引用的是B+树、智能指针、const与#define的区别、排序算法的时间复杂度

2020.10.07

排序算法的一些思考:为什么要分稳定排序和非稳定排序?

答:

  • 稳定的排序算法有:冒泡、插入、归并排序;非稳定的排序算法有:快速排序、堆排序等。
  • 稳定排序的一个例子:比如班里的同学已经按照学号拍好序了。现在要按照身高进行排序。如果是稳定排序好之后,身高相同的同学,学号还是按顺序的。
  • 所以其实稳定排序就是有两个排序关键字的时候,稳定排序可以让第一个关键字排序的结果继续服务与第二个关键字。

为什么MySQL要用B+树存储索引?

  1. 答:
    这个和业务场景有关,如果只选一个数据,那确实是hash更快。但是数据库中经常会选择多条,这时候由于B+树索引有序,并且又有链表相连,它的查询效率比hash就快很多了。
  2. 拓展
  • 二叉排序树:左边比根节点小,右边比根节点大,并且左右子树都是二叉排序树。

  • 之所以要用二叉平衡树,是因为让有节点不断插入的时候,能让它的节点尽可能均匀分布。

  • 红黑树其实就是平衡树的一种,它的复杂定义和规则,都是为了保证树的平衡性。Why?因为树的查找性能取决于树的高度,让树尽可能平衡,就是为了降低树的高度。
    C++的STL中set和map的底层实现就是红黑树。

  • B树是一种多路搜索树,它的每个节点可以拥有多于两个孩子节点。M路的B树最多能拥有M个孩子节点。
    设计成多路的原因依然是为了降低树的高度,但并不是越低越好,最低的时候就变成了有序数组了。
    B树一般用于文件系统的索引,文件系统和数据库的索引都是存储在硬盘上的,若数据量大,就不能一次性的加载到内存中。如果在内存中,红黑树比B树效率更高,但是涉及到磁盘操作,B树就更优了。
    在这里插入图片描述

  • B+树是在B树的基础上进行改造,它的数据都在叶子节点,同时叶子节点之间还加了指针形成链表。

2020.10.08

为什么要用智能指针?

  1. 答:
  • 对于C++中自动分配(new-delete)的对象,其生存期与它们在哪里创建是无关的,只有当显式的被释放时,这些对象才会销毁。
    为了更安全的使用动态对象,标准库定义了智能指针类型来管理动态分配的对象。当一个对象应该被释放时,指向它的智能指针可以确保自动的释放它。
  • 智能指针的用法:
    (1)shared_ptr允许多个指针指向同一个对象;
    (2)unique_ptr“独占”所指向的对象;
    (3)weak_ptr指向shared_ptr所管理的对象。
    三种类型都定义在memory头文件中。
  1. 拓展
  • 程序中对象的生存期:
    (1)全局对象:程序启动时分配,程序结束时销毁;
    (2)局部自动对象:进入定义所在的程序块时被创建,在离开块时销毁;
    (3)局部static对象:在第一次使用前分配,程序结束时销毁。
  • C++中,动态 内存的管理是通过一对运算符来完成的:new-delete。

const和#define相比的区别与优点:

  1. 区别:(1)起作用阶段:#define是在编译的预处理阶段起作用;而const是在编译、运行的时候起作用。
    (2)起作用的方式:#define只是简单地字符串替换,没有类型检查;而const有对应的数据类型,可以进行判断的,避免一些低级的错误。
    (3)存储方式:#define只是进行展开,有多少地方使用就替换多少次,其定义的宏常量在内存中有若干个备份;const定义的只读变量在程序运行过程中只有一份备份。
    (4)就代码调试的方便程度而言:const常量是可以进行调试的,#define是不能进行调试的,因为在预编译阶段就已经替换掉了。
  2. const的优点:(1)const有数据类型,可以进行类型检查;而宏常量没有数据类型。
    (2)const常量可以进行调试,但宏常量不能进行调试。
    (3)const可节省空间避免不必要的内存分配,提高效率。
  3. 还有很重要的一点:const推出的目的是为了取代预编译指令#define。
    为啥?
    因为:const的出现消除了预编译指令的缺点(即不能进行类型检测),同时继承了其优点(即可以提高代码的执行效率)。

2 关于经典排序算法的稳定性

  1. 稳定性:指的就是排序后2个相等的值的顺序和排序前的顺序是相同的
  2. 稳定排序和不稳定排序
    (1)稳定排序都有:冒泡、插入、归并和基数排序;
    (2)非稳定排序:选择排序、快速排序、希尔排序、堆排序。

3 关于经典排序算法的时间复杂度

  1. 时间复杂度大O表示法:大O表示法让你能够比较操作数,它指出了算法运行时间的增速。比如,列表包含n个元素,简单查找需要检查每个元素,因此需要执行n次操作,时间复杂度就为O(n)。
    比如:
    (1)时间复杂度为O(1)的算法:int n=100; n=n+1; cout<<n;
    (2)时间复杂度为O(n)的算法:for(int i=0;i<n;i++) {cout<<"Test";}
    (3)时间复杂度为O(n^2)的算法:for(int i=0;i<n;i++){ for(int j=0;j<n;j++) {cout<<"Test"}}
    (4)时间内复杂度为O(logn)的算法:int sum=1; while(sum<n) {sum = sum*2}。(因为2^x=n,所以内层语句执行了x = log(n)次)
  2. 经典排序算法的时间复杂度
    (1)时间复杂度为O(n^2)的排序:冒泡排序、插入排序、选择排序。
    (2)时间复杂度为O(nlog2n):快排、堆排序、归并排序。
    (3)希尔排序介于这两者之间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值