数据结构(一):顺序表(ArrayList)和链表(LinkedList)

前言

因之前没有系统学习过数据结构相关知识,所以从现在起将此部分知识过一遍,后续会将学习内容做总结记录。

一、数据结构相关概念

数据项:一个数据元素可以由若干数据项组成
数据对象:有相同性质的数据元素的集合,是数据的子集
数据结构:是相互之间存在一种或多种特定关系的数据元素的集合

逻辑结构:指数据对象中数据元素之间的相互关系,分别有集合结构、线性结构、树形结构、图形结构等。
物理结构:指数据的逻辑结构在计算机中的存储形式,包含顺序存储结构和链式存储结构

二、线性表之顺序表

1、 为什么会有线性表
首先要知道数组的特征:

  • 数组是最简单的数据结构;
  • 数组按顺序存储空间连续,但必须指定数组大小;
  • 数组空间效率低,经常有空闲区域未充分利用;
  • 数组的增加和删除操作麻烦;

因数据的这些特性故引进了线性表,线性表按照物理结构又可划分为 顺序存储结构链式存储结构

2、顺序表的基本原理
顺序表是指按逻辑次序依次存放在一组地址连续的存储单元的数据元素。

3、顺序表继承结构——ArrayList
迭代器接口用于轮询删除节点------hasNext()
------next()
------remove()
数据结构(一):顺序表(ArrayList)和链表(LinkedList)_第1张图片

4、 顺序表相关问题
4.1 ArrayList的大小是如何自动增加的?
add() 源码分析

4.2 什么情况下你会使用ArrayList?
优缺点:尾插效率高,支持随机访问(缺点:中间插入或者删除效率低)
应用场景:顺序查找(无增加和删除操作时)

4.3 在索引中ArrayList的增加或者删除某个对象的运行过程?效率很低吗?解释一下为什么?
效率低,arrayCopy()耗时

4.4 ArrayList如何顺序删除节点 ?
迭代器删除,最好从尾部往前删

4.5 ArrayList的遍历方法?
迭代器遍历–next
for循环遍历(for-each遍历亦可),但不能对其操作会有问题

5、leetcode 算法题
26题 删除排序数列中的重复项,这个题主要是要审题注意“排序数组”则能清晰解题思路

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums == null) return 0;
        int i = 0;
        for (int j = 1; j

35题 搜索插入位置,最开始我用的是遍历处理,但是若数据多则会很慢,效率低,所以改为官方推荐的二分法

// 遍历查询处理
class Solution {
    public int searchInsert(int[] nums, int target) {
        if(nums == null) return 0;
        int pos = nums.length;
        for(int i = 0; i < nums.length; i++){
            if(nums[i] >= target){
                pos = i;
                break;
            }
        }
        return pos;
    }
}
// 二分法
class Solution {
    public int searchInsert(int[] nums, int target) {
        int left =0; 
        int right = nums.length - 1;
        while(left <= right){
            int mid = (left + right)/2;
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] < target){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        return left;
    }    
}

34题 在排序数组中查找元素的第一个和最后一个

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] targetRange = {-1, -1};
        int leftIndex = insertIndex(nums, target, true);

        if(leftIndex == nums.length || nums[leftIndex] != target){
            return targetRange;
        }

        targetRange[0] = leftIndex;
        targetRange[1] = insertIndex(nums, target, false)-1;
        return targetRange;
    }

    // 重点!!!
    private int insertIndex(int[] nums, int target, boolean isLeft){
        int lo = 0;
        int hi = nums.length;
        while(lo < hi){
            int mid = (lo + hi)/2;
            if(nums[mid] > target || isLeft && (target == nums[mid])){
                hi = mid;
            }else{
                lo = mid + 1;
            }
        }
        return lo;
    }
}

三、线性表之链表

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的
数据元素,这组存储单元可以是连续的,也可以是不连续的
1、单链表
增删改查操作
继承结构

2、 双链表
增删改
继承机构

3、leetcode 算法题
21题 合并两个有序链表
24题 两两交换链表中的节点
138题 复制带随机指针的链表

4、其他
4.1 手写一个单链表,并且实现单链表元素的逆置,(a0, a1,a2,a3,…an)-> (an,an-1,… a1, a0),算法的空间复杂度和时间复杂度经可能低。

4.2 手写双向链表, 实现增删改查,并与源码Linkedlist比较异同点;

4.3 对比源码Arraylist 和LinkedList 的优缺点

四、线性表的对比

线性表类型 优缺点
顺序表 优点:存储空间连续;允许随机访问;尾插尾删方便;缺点:插入删除效率低;长度固定
单链表 优点:随意增删改且效率高;长度随意修改;缺点:内存不连续;不可随机查找
双链表 单链表所有优缺点,但效率比单链表快

五、LRU算法

1、什么是缓存
1.1 源于硬件,即CPU缓存,用于解决CPU速度与内存速度间的速度差异(CPU有多级缓存,内存不是很大,缓存级别越高缓存控件越大)
1.2 软件缓存有三级缓存,分别是内存缓存,数据库缓存和网络缓存(使得速度更快,占用内存成本更低)
1.3 内存缓存是指预先将数据写到容器如list\map\set等数据存储单元中

2、LRU算法
2.1 内存缓存淘汰机制有以下三种:
FIFO:
LFU:
LRU:

2.2 LRU算法规则
——新数据插入链表头部
——缓存命中的数据移到表头
——链表满时丢弃链表尾部数据

2.3 LRU算法代码实现
首先,写一个单链表LinkedList

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