数据结构Java源码分析

参考书籍《大话数据结构》,实现参考JDK1.8

线性表:

Java实现类有ArrayList,LinkedList

ArrayList:

动态容量数组的列表,扩展类有序数组
int size;//数据大小
Object[] data;//容量数组
默认数组是空数组,容量为0,默认增加容量值是10,DEFAULT_CAPACITY

扩容规则:传入扩容值为minCapacity,若当前数组是空数组,扩容值为max(minCapacity,DEFAULT_CAPACITY),否则判断minCapacity - size,若大于0默认将当前容量 + 当前容量扩大2倍为newCapacity,newCapacity若小于minCapacity,容量值为minCapacity,否则为newCapacity,然后进行数组拷贝生成新数组。

添加/插入:添加时先检查是否需要扩容,然后给size+1赋值,插入操作是检查插入位置是否在范围,不在范围就抛异常,在范围进行检查是否需要扩容,然后进行数据移动拷贝arraycopy(data,index,data,index+1,size - index),data[size++] = o,底层C实现,时间复杂度O(n)
删除:检查删除位置是否在范围,然后再进行数据移动拷贝(data,index + 1,data,index - 1, size - index - 1),data[--size] = null
查找/搜索:指定位置查找,O(1),对象查找indexOf(Object) 顺序查找O(n),
排序:冒泡排序O(n^2)
优缺点:顺序储存,索引查找快,增删慢

LinkedList(实现了Deque双端队列接口):

链表:动态容量的双向链式列表,扩展类有单向链表,循环链表,双向链表,静态链表

int size;//数据大小
Node<E> first;//头节点
Node<E> last;//尾节点

class Node<E>{
E item;//数据元素
Node<E> prev;//节点前驱
Node<E> next;//节点后驱
}
默认是空链表,容量为0

扩容规则:无数量限制,添加多少元素增加多少节点,数量为size
添加/插入

//默认添加是从尾部插入
Node l = last; 
Node newNode = (l,o,null);
last = newMode;
if(l== null) first = newNode; 
else l.next = newMode;
size++;

//头部插入
Node l = first;
Node newNode = (null,o,l);
first = newMode; 
if(l == null) last = newMode;
else l.prev = newMode;size++;

查找/搜索:双向链表通过传入的index/2判断从头部还是尾部遍历搜索,查找到节点E,次数为n/2,O(n)
删除:remove()方法默认删除头部,传入obj进行删除的话,步骤是先查找到节点S,然后进行链接清除

Node prev = s.prev;Node next = s.next;
if(prev != null){prev.next = next;s.prev=null;}else{first=next};
if(next != null){next.prev = prev;s.next=null;}else{last=next};
s.item = null;
size--;

具有Collection的操作方法
add();
remove();

具有队列Queue的操作方法
peek(),element();
offer();
poll();
E remove();

peek()方法取出队列头部元素时候,不删除该元素,而poll()方法取出元素时会删除元素。如果遇到队列为空的情况是,两者都会返回null,element()会抛出异常

双端队列Deque(继承队列接口,具有栈)的操作方法:
所有的操作方法peekFirst,peekLast.....
push()无空间会抛异常
pop()无元素会抛异常

优缺点:不受固定的存储空间限制,快速的插入和删除操作,整块集合插入为O(1),查询效率比顺序列表低,O(n)

栈和队列:

栈是限定仅在表尾进行插入和删除操作的线性表
队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表

栈/队列的二种实现:数组实现栈,队列,链表实现简述(见上面LinkedList)
ArrayDeque

object[] elements;//元素数组
int head;//头部数据的位置索引
int tail;//尾部数据的位置索引

扩容规则:默认长度16,传入值会转换成2^n,当头部head == tail时,说明没有位置可以储存数据,进行扩容2倍,然后将数据拷贝到新数组头部,head重新赋值0,tail赋值为原来的数组长度n

private void doubleCapacity() {
        assert head == tail;
        int p = head;
        int n = elements.length;
        int r = n - p; // number of elements to the right of p
        int newCapacity = n << 1;
        if (newCapacity < 0)
            throw new IllegalStateException("Sorry, deque too big");
        Object[] a = new Object[newCapacity];
        System.arraycopy(elements, p, a, 0, r);
        System.arraycopy(elements, 0, a, r, p);
        elements = a;
        head = 0;
        tail = n;
    }

添加/插入:设置后检测是否需要扩容

public void addFirst(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[head = (head - 1) & (elements.length - 1)] = e;
        if (head == tail)
            doubleCapacity();
    }

 public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();
    }

删除:删除前后元素时间复杂度为O(1),然后修改head或者tail,删除对象会遍历数组O(n),找到相应下标,然后移动拷贝整个数组
查找/搜索:获取前后元素为O(1)
排序:无
优缺点:查找元素,删除前后元素效率高,删除其他位置O(n)

栈(LIFO,FILO)常用方法是void push(),E pop(),操作失败抛出异常,默认调用的是addFirst,removeFirst
队列(FIFO)常用方法是boolean offer(E),E poll(),操作失败返回false,null,默认调用的是addLast,pollFirst

零个或多个字符组成的有限序列
String

char[] value;//字符数组
int hash;//hash值

固定长度,构造方法不传如数组或串,默认为空串"",不可变类,操作形成新的String对象

操作方法:
String(char[] arr)
String(String str)
String(byte[] bytes)
length()
getChars(char[] buf,int len)
isEmpty()
charAt(int index)
compareTo
startWith
indexOf
subString
replaceAll
split
concat

startWith,endWitdh
偏移length进行普通匹配算法O(n-m+1)

indexOf
普通匹配算法O(n-m+1)*m,KMP子串匹配算法O(n+m)

replaceAll
正则匹配实现

HashMap KV对集合,字典

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容