1、二叉搜索树的查找
(1)传统的递归
(2)非递归查找,就硬是循环得了
(3)遍历的递归与非递归方式
2、销毁二叉树的方法
(1)需要采用后续遍历的方式(左右中)可以采用递归,简单点
(2)注意传递二级指针或者指针引用
3、单项链表
(1)根据索引找到想要操作的节点就可以了
(2)删除全部节点时可以关注下二级指针的问题(避免野指针)
4、双向链表(双向就是循环了吗)
(1)注意在根据索引来查找节点时,判断下在前半部分还是后半部分,在通过next或pre偏移,可以有效的减少查找的次数
(2)主要是把想要操作的节点找出来,然后修改他们的前后指针的指向就没啥问题了,与单项链表差不多,复杂不到那里去。
5、栈的实现
(1)基于数组来实现:就用[0]来作为栈底元素,数组增长的方向为栈顶的方向,对数组尾巴进行压栈和出栈操作即可。
(2)基于单项链表的实现:用表头作为栈顶,每次的压栈都从表头开始插入,出栈也从表头进行,相对简单。
6、队列
(1)元素只能从队尾一端进入队列,元素只能从队首出队列
(2)基于数组实现的循环队列:因为每次从数组头部删除元素(出队)后,需要将头部以后的所有元素往前移动一个位置,时间复杂度位O(n)。如果知识把队首的标志往后移动,就会造成数组空间的流失。我们希望队列的插入和删除操作都是O(1),同时不造成空间的浪费,应该使用循环队列。所谓的循环队列,可以把数组看作一个首位相连的圆环,删除元素时将队首标志往后移动,添加元素时若数组尾部已经没有空间,则考虑数组头部是否空闲,如果是,则在数组的头部进行插入。
栈空:队首标志==队尾标志,表示栈空
栈满:队尾 + 1 == 队首,表示栈满。此时其实还有一个位置,不进行存储
(3)基于单向链表实现的队列:以链表头部作为队首,链表尾部作为队尾。存储一个指向队尾的指针,方便从链表尾部插入元素,使用表头,方便从队首删除元素。
7、字符串string实现
(1)string的拷贝构造要实现深拷贝,避免浅拷贝带来的内存共享导致的问题
(2)关于operator》和operator《运算符的重载,建议设计成友元函数,不设计成成员函数。因为如果是成员函数,必须通过对象来调用,不符合《》的使用习惯
8、哈希表(散列表)
(1)哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素(可以理解为散列表和散列函数)
(2)哈希表的主要思想是通过一个哈希函数,在所有可能的键与槽位之间建立一张映射表。哈希函数每次接受一个键,将返回与键对应的哈希编码或者哈希值。键的数据类型可能各种各样,但哈希值只能是整型。当哈希函数能够保证不同的键生成的哈希值互不相同时,就说哈希值能直接寻址想要的结果。
(3)哈希表的实现:其中的原理就是用哈希函数来将键值映射为数组的下标,存放对应的数据。哈希函数才是整个实现的关键。因为好的哈希函数要保证数据索引的均匀分配,不浪费空间,较少冲突。
(4)哈希函数设计的考虑因素
a、计算散列地址所需要的时间
b、关键字的长度
c、表长
d、关键字分布是否均匀,是否有规律
e、在满足以上条件的情况下尽量减少冲突
(4)处理冲突的方法:
a、链地址法:如果遇到冲突,会在原地址新建一个空间,然后以链表结点的形式插入到该空间中。
b、开放定制法:如果遇到冲突,按照一定的探测再散列的法则,向前寻找其他的地址空间,最终合起来算全部的地址位置。(线性探测、平方探测、随机探测等。。。)
(5)哈希表的查找效率
a、选用的哈希函数
b、选用的处理冲突的方法
c、哈希表的饱和度?