数据结构-算法-源码-复习

  • 最近并不是很忙,基础不能落下,不定期更新复习,会涉及Java,Python,GoLang:
  • 简单实现,有地方有错误,博客上未更改

线性表:

  • 什么是线性表:

    • 线性表指的是线性存储结构,可以理解为数组,所有数据一根线串一起,再存储到物理空间中
  • 具体实现:

    • Java

      • 参考实现:ArrayList:

      • 解析:

        • ArrayList内部有EMPTY_ELEMENTDATADEFAULTCAPACITY_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类型的变量都丢在常量池中,都指向同一个空数组,从而减少内存损耗
          • 总结:

            • 关于 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)
          
          

循环链表

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