数据结构总结

声明下:本博主基础薄弱,仅仅为了面试了解部分数据结构知识,详见大神博客,地址为:点击打开链接


表:

形如A0,A1,A2...An-1的一般数据表。

实现

基于数组实现的表(ArrayList)
  1. 内存分布连续;
  2. 可无限扩容的数组,扩容时,新建双倍容量的数组,将旧数组中的元素copy至新数组中,然后将旧数组引用指向新数组,即表示扩容;jdk7以上:ArrayList扩容为原来的1.5倍
  3. 优点:随机访问,时间复杂度为表:O(1)
  4. 缺点:插入和删除缓慢,要平均移动N/2个数组元素,时间复杂度为O(N),数组末尾插入和删除除外,O(1)。
基于链实现的表(LinkedList双链)
  1. 内存分布不连续,即节点之间内存不连续;
  2. 单链:链尾next指针指向null,双链:链尾指针指向链头元素。
  3. 一个节点包含:表元素和next链节点指针,指向下一个元素;
  4. 优点:插入和删除方便,只需要修改节点指针指向即可p=p.nextO(1)
  5. 缺点:随机访问缓慢,需要从链头开始遍历至查询的元素,O(N),但是链头元素除外;

集合使用注意:

  • iterator迭代器:如果在迭代过程中,对集合本身进行增加、修改、删除等操作,会引发ConcurrentModificationException异常,因为集合本身发生变化,iterator迭代不知道集合数目发生变化,所以会引起异常。所以要使用iterator自带的remove方法,当然java8以后ListIterator新加了Add方法
  • Remove方法:如果该集合多适用于删除场景,可以将list集合设置为LikedList集合,时间复杂度为O(1)

散列:(HashMap)

解决hash散列冲突方法:
  1. 分离链接法(HashMap):数组+链表:使用Hash算法避免冲突发生,HashMap重写hashcode方法,数组长度一般定义为2的n次幂,使用hashcode(key) & (length-1)与运算的到一个散列值,然后进行17或者20进行或运算,得到一个散列值;见博主hashmap 底层原理
  2. 线性探测法和平方探测法:当2位置出现冲突时,会查看3的位置,依次排查一遍,平方即探测平方位置上的的值是否为空;
  3. 再散列
  4. 建立一个公共溢出区:将数组表一分为二,一部分基础表一部分为存放冲突元素的;

栈stack:

插入和删除在同一个位置上进行,先进后出
应用:编译器检查语法错误

队列Queue:

插入在队尾,删除在队头,即先进先出,
应用:排队系统,秒杀系统

树:

基本概念:
  1. 高度指结点的高度,即某结点到叶子结点的距离
  2. 深度指:树的深度,即根节点到某结点之间的距离
  3. 度指结点的子树个数;

二叉树: 每个结点的子节点树不超过两个即为二叉树。
二叉查找树: 对于树的每个结点X,它的左子树所有子节点值小于X,右子树的所有子节点大于X
平均深度为:O(logN), N为树的高度,这里注意在计算机科学领域中,若无特殊说明, 对数都是以2为底的

二叉树的性质:
  1. 总结点数-1=总的连接数;例如度为0的结点数为n0,度为1的结点数为n1,度为2的结点数为n2,则n总结点数为n0+n1+n2,
n-1=n0+n1+n2=0Xn0+n1+2n2(总链条数)------>n0=n2+1

  1. 高度为k的二叉树中,最多有2^n  -1个结点(满二叉树),最少有2^(k-1)个结点数
二叉树的遍历:
  1. 先序遍历;父辈先执行,儿子后执行
  2. 中序遍历;先处理左子树,然后执行当前结点,然后右子树
  3. 后序遍历;儿子先执行,父辈后执行
  4. 层序遍历;即从上到下按层次访问该树,每一层单独输出一行,每一层要求访问的顺序为从左到右我们在遍历的过程中将该层节点的孩子节点压入一个队列,这样就可以实现从上到下一层一层地遍历该二叉树
这里介绍几个数据查找的方法:
折半查找或者二分法:
要求:顺序表,有序
特点:平均查找时间O(logN)
方法:先和中间的元素比较,如果相等即返回,如果大于中间元素,则从中间元素后开始查找,如果小于中间元素,则从开始重新查找。
代码示例如下:
方法一:
public int compare(String[] strings, String value) {
    int low = 0;
    int length = strings.length - 1;
    while (low < length) {
        //如果中间的值比目标值大,则取0-mid-1)之间进行筛选
        int mid = (low + length) / 2;
        if (strings[mid].compareToIgnoreCase(value) > 0) {
            length = mid - 1;
        } else if (strings[mid].compareToIgnoreCase(value) < 0) {
            //如果中间值比目标值小,则取(mid+1-length之间的 进行筛选
            low=mid+1;
        }
        return mid;
    }
    return -1;
}
方法二:
//first指开始查找元素的索引,size指末尾段元素的索引
public static int search(int[] a,int first,int size,int target){
    int middle;
    if (size<0){
        return -1;
    }
    middle=first+size/2;
    if (target<a[middle]){
        return search(a,first,size/2,target);
    }
    if (target>a[middle]){
        return search(a,middle+1,(size-1)/2,target);
    }
    if (target==a[middle]){
        return middle;
    }
    return -1;
}




顺序查找法:不需要排序,直接一个一个查找









平均步长为:(N+1)/2,时间复杂度为:O(N)
代码如下:
public static int binarySearch(String[] strings, String value){
        for (int i=0;i<strings.length;i++){
            if (strings[i].equals(value)){
                return i;
            }
        }
        return -1;
}





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值