- 最近并不是很忙,基础不能落下,不定期更新复习,会涉及Java,Python,GoLang:
- 简单实现,有地方有错误,博客上未更改
线性表:
-
什么是线性表:
- 线性表指的是线性存储结构,可以理解为数组,所有数据一根线串一起,再存储到物理空间中
-
具体实现:
-
Java
-
参考实现:ArrayList:
-
解析:
-
ArrayList内部有EMPTY_ELEMENTDATA 和DEFAULTCAPACITY_EMPTY_ELEMENTDATA 两个元素,连个元素的作用,及其区别:
这两个都是空数组
-
当 使用 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的时候,意味着 默认的容量为10 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } 当add的时候,才会设置容量为10: private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } // 计算容量 private static int calculateCapacity(Object[] elementData, int minCapacity) { // 如果是默认的空数组的话,则会将容量与最小值匹配取最大值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { // 用于快速失败机制 modCount++; // 当最小值容量大于当前元素的长度的时候就会发生扩容,并不是达到 1/2 就会扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { int oldCapacity = elementData.length; // 在老容量的基础上扩容 1半 int newCapacity = oldCapacity + (oldCapacity >> 1); // 同时,如果扩容之后的大小超过了最大限定的话,则会再扩容到最大值: Integer.MAX_VALUE if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 拷贝达到扩容效果 elementData = Arrays.copyOf(elementData, newCapacity); }
-
问题:
- 还有一个EMPTY_ELEMENTDATA,这个的作用是什么:
- 答案:
是为了提升性能:
- EMPTY_ELEMENTDATA在当容量为空的时候才会使用,并且在Java7中,并不存在EMPTY_ELEMENTDATA ,而只有DEFAULTCAPACITY_EMPTY_ELEMENTDATA,每当创建一个ArrayList的时候,都会发生this.elementData = new Object[initialCapacity];,所以当ArrayList实例过多的时候,内存中会存在大量的空数组,而final类型的变量都丢在常量池中,都指向同一个空数组,从而减少内存损耗
- 答案:
- 还有一个EMPTY_ELEMENTDATA,这个的作用是什么:
-
总结:
- 关于 ArrayList,add的时候才会发生扩容,通过与空数组判断相等从而判定阈值
- 编码建议: 对于线程无关的数据,大可模仿此种做法达到内存降低(变量共享))
-
-
-
-
链表的定义:
- 链表是一种递归的数据结构,或者为空,或者指向下一个元素
复杂度分析:
-
查找时间复杂度: O(n): 需要遍历匹配
-
插入的时间复杂度: O(1) 或者O(n) :
- O(1) 表示: 插入节点的上一个节点已知,无需遍历
- O(n)表示: 插入节点未知,需要遍历获取,再插入
-
删除的时间复杂度同插入: O(1)或者O(n)
单向链表:
- 什么是单向链表:
单向链表每个节点只有指针域和数据域,指针域指向下一个节点
Java实现
@Data
public class MyLinkedList<T>
{
@Data
class ListNode<T>
{
private T data;
private ListNode<T> next;
public ListNode()
{
}
}
private ListNode<T> head;
private int size;
public MyLinkedList()
{
}
// 添加
public void add(T value)
{
ListNode<T> listNode = new ListNode<>();
listNode.setData(value);
if (this.head == null)
{
this.head = listNode;
} else
{
ListNode<T> tempNode = this.head;
while (tempNode.next != null)
{
tempNode = tempNode.getNext();
}
tempNode.next = listNode;
}
}
// 删除 节点,需要先连再断,所以需要保存上一个节点
public void remove(T value)
{
ListNode<T> tempNode = this.getHead();
while (tempNode != null)
{
if (null != tempNode.next && tempNode.next.getData().equals(value))
{
ListNode<T> prevNode = tempNode;
prevNode.setNext(tempNode.getNext());
tempNode.setNext(null);
break;
}else{
tempNode=tempNode.next;
}
}
}
// 查询
public boolean contains(T value)
{
ListNode<T> tempNode = this.getHead();
while (tempNode != null)
{
if (tempNode.getData().equals(value))
{
return true;
}
tempNode=tempNode.next;
}
return false;
}
}
GoLang实现
type SingleLinkedListNode struct {
Data interface{}
Next *SingleLinkedListNode
}
type MySingleLinkedList struct {
Head *SingleLinkedListNode
Tail *SingleLinkedListNode
Size int
}
func (this *MySingleLinkedList) Add(value interface{}) error {
newNode := &SingleLinkedListNode{
Data: value,
}
if nil == this.Head {
this.Head = newNode
} else {
this.Tail.Next = newNode
}
this.Tail = newNode
return nil
}
func (this *MySingleLinkedList) Remove(value interface{}) error {
tempNode := this.Head
for nil != tempNode {
if nil != tempNode.Next && tempNode.Next.Data == value {
prevNode := tempNode
prevNode.Next = tempNode.Next
tempNode.Next = nil
}else{
tempNode=tempNode.Next
}
}
return nil
}
Python 实现:
-
class MySingleLinkedListNode(object): __slots__ = ('data', 'nextV') def __init__(self): self.data = None self.nextV = None def __str__(self): return 'data=%s' % self.data class MySingleLinkedList(object): __slots__ = ('head', 'tail', 'size', 'cursor') def __init__(self): self.head = None self.tail = self.head self.cursor = 0 self.size = 0 def add(self, value): newNode = MySingleLinkedListNode() newNode.data = value if self.head is None: self.head = newNode else: self.tail.nextV = newNode self.tail = newNode self.size += 1 def remove(self, value): tempNode = self.head while tempNode is not None: if tempNode.next is not None and tempNode.next.data == value: prevNode = tempNode prevNode.next = tempNode.next tempNode.next = None break else: tempNode = tempNode.next def __iter__(self): return self def __next__(self): i = 0 tempNode = self.head while i < self.cursor and tempNode is not None and i < self.size: i += 1 tempNode = tempNode.nextV if self.cursor < self.size: self.cursor += 1 return tempNode def print(self): tempNode = self.head while tempNode is not None: print(tempNode) tempNode = tempNode.nextV mys = MySingleLinkedList() mys.add(1) mys.add(2) mys.print() for v in mys: if v is not None: print(v)
双向链表
- 什么是双向链表:
双向链表指的是节点不仅连接着后继节点,也连接着前驱节点
Java实现:
-
源码解析:参考LinkedList
- LinkedList有2个成员变量:
- transient Node first;
- transient Node last;
- 添加
public boolean add(E e) { linkLast(e); return true; } 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++; }
-
添加采用的是尾插法,
-
删除:
-
public E remove() { return removeFirst(); } public E removeFirst() { // 将首节点作为局部变量,减小生命周期 final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } private E unlinkFirst(Node<E> f) { final E element = f.item; // 保存下一个节点,这个节点作为之后的首节点 final Node<E> next = f.next; f.item = null; f.next = null; // help GC first = next; // 如果下一个节点为空,代表着整个list为空 if (next == null) last = null; else // 不是双向循环链表,所以需要将前置节点置空 next.prev = null; size--; // 快速失败机制 modCount++; return element; }
-
删除,默认是删除的首节点
-
删除某个下标的节点:
-
public E remove(int index) { checkElementIndex(index); return unlink(node(index)); } 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; } } // 断开链接,prev需要指向cur的next ,cur的next需要指向cur的prev // 然后cur的next,prev全指向空 // 唯一需要注意的就是删除的是否是头节点或者是尾节点 E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; // 删除的是首节点 if (prev == null) { first = next; } else { // 将prev的next指向cur的next prev.next = next; // 断开cur的next x.prev = null; } // 删除的是尾节点 if (next == null) { last = prev; } else { // 将next的prev指向cur的prev next.prev = prev; // 断开cur的next x.next = null; } x.item = null; size--; modCount++; return element; }
-
-
Java实现:
-
@Data public class MyDoubleLinkedList<T> implements Iterable<T> { @Override public Iterator<T> iterator() { return new MyDlIterator(); } @Data class DoubleLinkedListNode<T> { private T data; private DoubleLinkedListNode<T> prev; private DoubleLinkedListNode<T> next; } private DoubleLinkedListNode<T> head; private DoubleLinkedListNode<T> tail; private int size; public void add(T value) { DoubleLinkedListNode<T> newNode = new DoubleLinkedListNode<>(); newNode.setData(value); linkLast(newNode); } private void linkLast(DoubleLinkedListNode<T> node) { final DoubleLinkedListNode<T> tail = this.tail; if (this.head == null) { this.head = node; } else { tail.next = node; node.prev = tail; } this.tail = node; this.size++; } // 将数据插入到指定位置中 public void insert(T value, int index) { // 校验index if (!this.checkIndex(index)) throw new IndexOutOfBoundsException(); DoubleLinkedListNode<T> newNode = new DoubleLinkedListNode<>(); newNode.setData(value); // 插入的时候需要 获取到 插入位置的节点Cur,cur 是newNode的下一个节点,以及上一个节点prev // 并不需要减1,因为node持有prev的引用 DoubleLinkedListNode<T> tempNode = this.head; for (int i = 0; i < index; i++) { tempNode = tempNode.next; } if (null != tempNode.prev) { tempNode.prev.next = newNode; newNode.prev = tempNode.prev; } newNode.next = tempNode; tempNode.prev = newNode; this.size++; } // 删除指定位置的元素 public DoubleLinkedListNode<T> remove(int index) { if (!this.checkIndex(index)) throw new IndexOutOfBoundsException(); DoubleLinkedListNode<T> tempNode = this.head; for (int i = 0; i < index; i++) { tempNode = tempNode.next; } final DoubleLinkedListNode<T> prev = tempNode.prev; final DoubleLinkedListNode<T> cur = tempNode; final DoubleLinkedListNode<T> next = tempNode.next; if (prev != null) { prev.next = next; tempNode.prev = null; } if (next != null) { next.prev = prev; tempNode.next = null; } this.size--; return cur; } class MyDlIterator<T> implements Iterator<T> { private int cursor; @Override public boolean hasNext() { return this.cursor < MyDoubleLinkedList.this.size; } @Override public T next() { DoubleLinkedListNode<T> tempNode = (DoubleLinkedListNode<T>) MyDoubleLinkedList.this.head; for (int i = 0; i < this.cursor; i++) { tempNode = tempNode.next; } this.cursor++; return tempNode.data; } @Override public void remove() { } @Override public void forEachRemaining(Consumer action) { } } private boolean checkIndex(int index) { if (index < 0 || index > this.size) { return false; } return true; } public static void main(String[] args) { MyDoubleLinkedList<Integer> myDoubleLinkedList = new MyDoubleLinkedList<>(); myDoubleLinkedList.add(1); myDoubleLinkedList.add(2); for (Integer integer : myDoubleLinkedList) { System.out.println(integer); } }
-
-
GoLang实现:
-
type MyDoubleLinkedListNode struct { Data interface{} Next *MyDoubleLinkedListNode Prev *MyDoubleLinkedListNode } type MyDoubleLinkedList struct { Head *MyDoubleLinkedListNode Tail *MyDoubleLinkedListNode Size int } func (this *MyDoubleLinkedList) Add(value interface{}) error { newNode := &MyDoubleLinkedListNode{ Data: value, } return this.LinkLast(newNode) } func (this *MyDoubleLinkedList) LinkLast(node *MyDoubleLinkedListNode) error { if this.Head == nil { this.Head = node } else { this.Tail.Next = node node.Prev = this.Tail } this.Tail = node this.Size++ return nil } func (this *MyDoubleLinkedList) Insert(value interface{}, index int) error { if e := this.checkIndex(index); nil != e { return e } newNode := &MyDoubleLinkedListNode{ Data: value, } // 插入到末尾 if index == this.Size { return this.LinkLast(newNode) } tNode := this.Head for i := 0; i < index-1; i++ { tNode = tNode.Next } prev := tNode.Prev next := tNode if nil != prev { prev.Next = newNode newNode.Prev = prev } else { // 说明是首节点 this.Head = newNode } if nil != next { next.Prev = newNode } else { // 说明是尾节点 this.Tail = newNode } newNode.Next = next this.Size++ return nil } func (this *MyDoubleLinkedList) checkIndex(index int) error { if index < 0 || index > this.Size { return errors.New("index out of range ,index begin with 0") } return nil } func (this *MyDoubleLinkedList) Remove(index int) error { if e := this.checkIndex(index); nil != e { return e } tNode := this.Head for i := 0; i < index; i++ { tNode = tNode.Next } prev := tNode.Prev next := tNode.Next prev.Next = next next.Prev = prev tNode.Next, tNode.Prev = nil, nil this.Size-- return nil } func (this *MyDoubleLinkedList) Foreach() { tNode := this.Head for nil != tNode { fmt.Println(tNode.Data) tNode = tNode.Next } }
-
-
Python实现:
-
class MyDoubleLinkedListNode(object): __slots__ = ('data', 'next', 'prev') def __str__(self): print('value is %s' % self.data) class MyDoubleLinkedList(object): __slots__ = ('head', 'tail', 'size') def __init__(self): self.head = None self.tail = None self.size = 0 def add(self, value): newNode = MyDoubleLinkedListNode() newNode.data = value if self.head is None: self.head = newNode else: self.tail.next = newNode newNode.prev = self.tail self.tail = newNode self.size += 1 def insert(self, index, value): newNode = MyDoubleLinkedListNode() newNode.data = value self.check_index(index) if index == self.size: self.link_last(newNode) else: self.link_before(index, newNode) def link_last(self, node): if self.head is None: self.head = node else: node.prev = self.tail self.tail.next = node self.tail = node self.size += 1 def link_before(self, index, node): i = 0 tNode = self.head while i < index: tNode = tNode.next i += 1 prev = tNode.prev if prev is not None: prev.next = node node.prev = prev else: self.head = node if tNode is not None: node.next = tNode tNode.prev = node else: self.tail = node self.size += 1 def remove(self, index): self.check_index(index) i = 0 tNode = self.head while i < index: i += 1 tNode = tNode.next prev = tNode.prev next = tNode.next cur = tNode if prev is not None: prev.next = next else: # 说明是头节点 self.head = next if next is not None: next.prev = prev else: # 说明是尾节点 self.tail = next cur.next = None cur.prev = None self.size -= 1 def check_index(self, index): if index < 0 or index > self.size: raise IndexError('index out of range') def __iter__(self): itr = MyDoubleLinkedList.InternalIterator(self) return itr class InternalIterator(object): cursor = 0 def __init__(self, outter): self.outter = outter def __next__(self): if self.cursor >= self.outter.size: raise StopIteration else: i = 0 tNode = self.outter.head while i < self.cursor: tNode = tNode.next i += 1 self.cursor += 1 return tNode myD = MyDoubleLinkedList() myD.add(1) myD.add(2) myD.add(3) for v in myD: if v is not None: print(v.data) myD.insert(2, 4) for v in myD: print(v.data)
-
-
- LinkedList有2个成员变量: