数据结构与算法基础

数据结构与算法

栈是一种动态集合,它是一种LIFO(last in first out后进先出)结构。

#include <stack>
stack<int> stk;
stk.empty();	//空判断
stk.push();	//压栈
stk.top();	//返回栈顶
stk.pop();	//移除栈顶

队列

队列是一种动态集合,它是一种FIFO(first in first out先进先出)结构。

链表

struct ListNode {
    int val;
    struct ListNode *next;
};

二叉树

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
};

http://blog.51cto.com/ahalei/1425314
http://blog.51cto.com/ahalei/1427156

二叉树是一种特殊的树。二叉树的特点是每个结点最多有两个儿子,左边的叫做左儿子,右边的叫做右儿子,或者说每个结点最多有两棵子树。

二叉树中还有连两种特殊的二叉树叫做满二叉树和完全二叉树。

如果二叉树中每个内部结点都有两个儿子,这样的二叉树叫做满二叉树。或者说满二叉树所有的叶结点都有同样的深度。比如下面这棵二叉树,是不是感觉很“丰满”。满二叉树的严格的定义是一棵深度为 h h h 且有 2 h − 1 2^h-1 2h1 (等比数列求和)个结点的二叉树。

满二叉树

如果一棵二叉树除了最右边位置上一个或者几个叶结点缺少外其它是丰满的,那么这样的二叉树就是完全二叉树。严格的定义是:若设二叉树的高度为h,除第h层外,其它各层(1~h-1)的结点数都达到最大个数,第h层从右向左连续缺若干结点,就是完全二叉树。也就是说如果一个结点有右子结点,那么它一定也有左子结点。例如下面这三棵树都是完全二叉树。其实你可以将满二叉树理解成是一种特殊的或者极其完美的完全二叉树。

完全二叉树完全二叉树完全二叉树

一棵完全二叉树如何存储呢?其实完全二叉树中父亲和儿子之间有着神奇的规律,我们只需用一个一维数组就可以存储完全二叉树。首先将完全二叉树进行从上到下,从左到右编号。

通过上图我们发现如果完全二叉树的一个父结点编号为k,那么它左儿子的编号就是2k,右儿子的编号就是2k+1。如果已知儿子(左儿子或右儿子)的编号是k,那么它父结点的编号就是k/2。另外如果一棵完全二叉树有N个结点,那么这个完全二叉树的高度为log2 N简写为log N,即最多有log N层结点。完全二叉树的最典型应用就是—堆。

堆是什么?是一种特殊的完全二叉树,就像下面这棵树一样。

堆

有没有发现这棵二叉树有一个特点,就是所有父结点都比子结点要小。符合这样特点的完全二叉树我们称为最小堆。反之,如果所有父结点都比子结点要大,这样的完全二叉树称为最大堆。

二叉树遍历
深度优先DFS(Depth First Search)

深度优先遍历,需要用到栈(Stack)这种数据结构。栈的特点是先进后出。
二叉树前序、中序、后序遍历。

广度优先BFS(Breadth First Search)

广度优先遍历,需要用到队列(Queue)这种数据结构。队列的特点是先进先出。
二叉树层序遍历。

排序

八大排序算法
各种排序算法的动画比较

冒泡排序

就如名字说的,每经过一轮排序,将最大的数沉到最底部。

快速排序

快速排序的思想是以一个数为中心,通常这个数是该数列第一个数,将整个数列分为两个部分,一个部分是大于这个数的区域,一个部分是小于这个数的区域。然后再对这两个部分的数列分别排序。如果将数列分为两个部分是通过,一方面从后向前的搜索,另一方面从前向后的搜索来实现的。

堆排序

是指利用堆这种数据结构所设计的一种排序算法。

递归与循环

斐波那契数列(自底向上,使用迭代;自顶向下,使用递归)

如果需要重复地多次计算相同的问题,通常可以选择用递归或者循环两种不同的方法。
递归是在一个函数的内部调用这个函数自身。
循环是通过设置计算的初始值及终止条件,在一个范围内重复运算。
通常递归的代码会比较简洁。在上面的例子里,递归的代码只有一个语句,而循环则需要4个语句。在树的前序、中序、后序遍历算法的代码中,递归的实现明显要比循环简单得多。在面试的时候,如果面试官没有特别的要求,应聘者可以尽量多采用递归。
递归虽然有简洁的优点,但它同时也有显著的缺点。递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址及临时变量,而且往栈里压入数据和弹出数据都需要时间。这就不难理解有些例子中递归实现的效率不如循环。
另外,递归中有可能很多计算都是重复的,从而对性能带来很大的负面影响。递归的本质是把一个问题分解成两个或者多个小问题。如果多个小问题存在相互重叠的部分,那么就存在重复的计算。
除了效率之外,递归还有可能引起更严重的问题:调用栈溢出。前面分析中提到需要为每一次函数调用在内存栈中分配空间,而每个进程的栈的容量是有限的。当递归调用的层级太多时,就会超出栈的容量,从而导致调用栈溢出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值