数据结构和算法

1、数据结构

堆栈stack 先进后出 后进先出
队列queue 先进先出 后进后出
双端队列deque 两端可以进出
链表slink
双向链表dlink
二叉树btree
链表:
(1) 内存是不连续的
(2) 访问效率比较低 因为需要从第一个元素开始遍历
(3) 在任何地方插入和删除的效率都比较高 (只需要改变指针的值)
单向链表的节点:
节点元素
下一个节点的地址
逆序: 把一个链表中的元素逆序
树二叉树
任何一棵树 可以有 左右子树
struct TNode{
T data;
struct TNode left;
struct TNode right;
};
搜索树、有序树、排序树
左子树所有的元素都小于(大于)或者等于根节点的元素
右子树所有的元素都大小(小于)或者等于根节点的元素
任意一个树的节点都可以当作一棵树
中序遍历:先遍历左(右)子树,输出根节点,再遍历右(左)子树
右序遍历 后序遍历:先遍历左(右)子树,然后遍历右(左)子树,最后输出根节点
左序遍历 先序遍历 前序遍历:先输出根节点,再遍历左(右)子树,最后遍历右(左)子树
满二叉树
叶子结点全部在同一个高度 且除了叶子结点以外,所有的节点都有左右子节点
一棵高度为h的二满二叉树,一共有多少个节点 (2^h - 1)
平衡二叉树
从任意一个节点开始,左右子树的高度差不会超过1
完全二叉树
除了最后一层以外,满二叉树 最后一层的叶子结点必须是从左到右
定理:
1.对于一棵高度为h的树,最多有 (2^h -1)个节点
2.对于节点数为n的二叉树,至少有 log(n) + 1 高
3.对于一棵二叉树的第i层,最多有 2^(i-1) 个节点
红黑树
查找效率最高的
存储
红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3. 每个红色节点的两个子节点都是黑色。
(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
对于一棵完全二叉树
如果对所有节点从1开始依次编号
则第i个节点的左右子节点为 2
i, 2
i+1
如果从0开始编号,则左右子节点为 2i+1,2i+2
int arr[] = {2,4,9,7,3,1,5,8,0,6}

2、十个排序

排序
插入排序:直接插入,折半插入,希尔排序,
选择排序:堆排序,直接选择,鸡尾酒排序,
交换排序:冒泡排序,快速排序,
其他:归并排序,计数排序,基数排序,
常用的十种排序

(1)直接插入 思路:
假设现在是第i个元素 前面i-1个元素都有序 把arr[i]插入到前面i-1元素中使数组保持有序
从第一个元素开始到最后一个元素,依次往前面插入,使插入一个元素之后 该局部有序
(2)折半插入 思路:
利用二分查找法,先找到要插入的位置,将要插入位置之后的数都后移一位,再插入该元素
(3)希尔排序 第一个突破O(n^2)的排序算法 时间复杂度可最低到达O(n^1.3) 思路:
把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

(4)堆排序 思路:
把数组看作是一个完全二叉树
把完全二叉树调整成大栈堆(小栈堆)
从最后一个有子节点的节点(len/2 - 1)开始往前调整 每一个节点都需要调整
调整指定的节点方法:
得到左子节点 如果有左右节点 比较左右节点的值 哪个值大记录哪个子节点的下标位置
需要调整的节点 和 左右节点的较大值 进行比较
如果调整的这个节点的值 比 左右节点的较大值要 小 用较大值覆盖当前这个节点
把当前节点的值 放到了子节点上,所以子节点需要重新判断
从最后一个元素,和第一个元素交换 除去最后一个元素后调整下标为0的节点为大栈堆的,最终有序
(5)选择 思路:
遍历数组 能够 记录 最大值 的下标
把最大值 和 最后一个元素交换
遍历第二遍(不需要最后一个)数组 又能记录一个最大值的下标
把最大值 和 倒数第二个元素进行交换
循环len-1次,数组有序
(6)鸡尾酒 思路:
每次记录最大值和最小值的下标
最大值放末尾 最小值放开始
循环len/2次,数组有序

(7)冒泡 思路:
每两个元素进行比较 把较大值放后面 较小值放前面
把数据中的元素都比较一次之后,最大值已经冒到最末尾了
所以再遍历一次第二大的元素也到达倒数第二个位置
有n个元素循环n次即可完成排序
(8)快速 思路:
对于任何一个数,在队列中有一个位置,使得左边的数小于等于这个数,右边的数大于等于这个数,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

(9)归并 思路:
把两个有序的数组合并成一个有序的数组
(10)计数排序 适用于在某个比较小的区间内数据密度比较大的情况下思路:
找到最大值和最小值,将所有的数用数组下标的方式记录,再按照顺序输出,完成排序
(11)基数排序 思路:
将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

冒泡、选择、直接插入、二分插入 平均时间复杂度O(n^2)
堆排序、希尔排序、归并、快速 平均时间复杂度O(nlogn)

什么是时间复杂度:随着数据量n的增大,算法所需要的时间和n的增长速率之间的关系
衡量一个算法好与坏:
(1)时间复杂度 平均时间复杂度
随着数据量n的增大,算法所需要的时间和n的增长速率之间的关系
冒泡、选择(cook)、直接插入、二分插入 O(n^2)
归并、快速、堆 O(nlogn)
希尔 O(n^1.3)
基数 O(d(n+r))
计数 O(n)
(2)空间复杂度
随着数据量n的增大,算法所需要的额外的内存空间和n的增长率之间的关系
排序的稳定性:
假设数列中有相等的元素arr[i]和arr[j],且i 稳定排序:冒泡、选择、插入、计数、基数
不稳定的排序:快速 希尔 堆
任何一个算法
1.至少有0个输入
2.至少有1个输出
3.有穷性
4.确定性

你可能感兴趣的:(数据结构和算法)