Java基础随笔2

继续上回:

————————————————————————————————————————————————————————————————————————————————

以下部分转自:https://github.com/crossoverJie/Java-Interview/blob/master/MD/LinkedList.md

LinkedList 底层分析

如图所示 LinkedList 底层是基于双向链表实现的,也是实现了 List 接口,所以也拥有 List 的一些特点(JDK1.7/8 之后取消了循环,修改为双向链表)。

新增方法

    public boolean add(E e) {
        linkLast(e);
        return true;
    }
     /**  * Links e as last element.  */ void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }

可见每次插入都是移动指针,和 ArrayList 的拷贝数组来说效率要高上不少。

查询方法

    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
    
    Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }

由此可以看出是使用二分查找来看 index 离 size 中间距离来判断是从头结点正序查还是从尾节点倒序查。

  • node()会以O(n/2)的性能去获取一个结点
    • 如果索引值大于链表大小的一半,那么将从尾结点开始遍历

这样的效率是非常低的,特别是当 index 越接近 size 的中间值时。

总结:

  • LinkedList 插入,删除都是移动指针效率很高。
  • 查找需要进行遍历查询,效率较低。

————————————————————————————————————————————————————————————————————————————————————————————

LinkedList内容较为简单,没什么特别难得内容。查找时主要使用的是二分查找,这里顺便总结以下相关的查找算法。

1.顺序查找(最无脑查找)适合于存储结构为顺序存储或链接存储的线性表,顺序查找的时间复杂度为O(n)。

int SequenceSearch(int a[], int value, int n)
{
    int i;
    for(i=0; i<n; i++)
        if(a[i]==value)
            return i;
    return -1;
}

2.二分查找

元素必须是有序的,如果是无序的则要先进行排序操作,期望时间复杂度为O(log2n);

//二分查找,直接对半
int BinarySearch1(int a[], int value, int n)
{
int low, high, mid;
low = 0;
high = n-1;
while(low<=high)
{
mid = (low+high)/2;
if(a[mid]==value)
return mid;
if(a[mid]>value)
high = mid-1;
if(a[mid]<value)
low = mid+1;
}
return -1;
}

//二分查找,递归版本
int BinarySearch2(int a[], int value, int low, int high)
{
int mid = low+(high-low)/2;
if(a[mid]==value)
return mid;
if(a[mid]>value)
return BinarySearch2(a, value, low, mid-1);
if(a[mid]<value)
return BinarySearch2(a, value, mid+1, high);
}

3. 插值查找

基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找。查找成功或者失败的时间复杂度均为O(log2(log2n))。

//插值查找
int InsertionSearch(int a[], int value, int low, int high)
{
int mid = low+(value-a[low])/(a[high]-a[low])*(high-low);
if(a[mid]==value)
return mid;
if(a[mid]>value)
return InsertionSearch(a, value, low, mid-1);
if(a[mid]<value)
return InsertionSearch(a, value, mid+1, high);
}

先列出三个简单的查找,后面重学数据结构和算法的时候再记录其他的树查找、哈希查找等等。

猜你喜欢

转载自www.cnblogs.com/Aurel1ano/p/9185301.html