链表

链表是一种用于存储数据集合的数据结构。链表有以下属性:

  • 相邻元素之间通过指针连接。

  • 最后一个元素的后继指针为NULL。

  • 在程序执行过程中,链表的长度可以增加或缩小。

  • 链表的空间能按需分配(直到内存耗尽)。

  • 没有内存空间的浪费(但链表中的指针需要一些额外的内存开销)
    Snipaste_2019-05-09_20-06-30.jpg

与链表对应的数组

整个数组所有的元素都存储在操作系统分配的一块内存中。访问该数组内的元素时,根据数组元素数据类型的存储空间大小,数组对象的基地址和要访问的元素距基地址的偏移量,就可以在常数时间内计算出元素的地址。

1、因此数组的优点有

  • 简单且易用
  • 访问元素快(常数时间)

2、数组的缺点有

  • 大小固定:数组的大小静态的(在使用前指定数组的大小)
  • 分配一个连续的空间块
  • 基于位置的插入操作实现复杂

单向链表

链表通常指单向链表,它包含多个结点,每个结点有一个指向后继元素的next(下一个)指针。表中最后一个结点的next指针为NULL,表示该链表的结束:
Snipaste_2019-05-09_20-34-10.jpg

实现:

public class ListNode {
	private int data;
	private ListNode next;
	public ListNode(int data) {
		this.data = data;
	}
	public int getData() {
		return data;
	}
	public void setData(int data) {
		this.data = data;
	}
	public ListNode getNext() {
		return next;
	}
	public void setNext(ListNode next) {
		this.next = next;
	}
	
	// 链表的遍历
	public void listPrint(ListNode headNode) {
		ListNode currentNode = headNode;
		while(currentNode != null) {
			System.out.print(currentNode.getData()+" ");
			currentNode = currentNode.getNext();
		}
	}
	// 统计链表的长度
	public int listlength(ListNode headNode) {
		int length = 0;
		ListNode currentNode = headNode;
		while(currentNode != null) {
			length++;
			currentNode = currentNode.getNext();
		}
		return length;
	}
	
	// 链表的插入
	public ListNode InsertLinkedList(ListNode headNode, ListNode nodeToInsert, int position) {
		if (headNode == null){ // 若链表为空,插入
			return nodeToInsert;
		}
		int size = listlength(headNode);
		if(position > size+1 || position < 1) {
			System.out.println("Position of node to insert is invalid. The valid inputs are 1 to"+ (size+1));
			return headNode;
		}
		if(position == 1) { // 在链表开头插入
			nodeToInsert.setNext(headNode);
			return nodeToInsert;
		} else { 	// 在中间或者末尾插入
			ListNode previousNode = headNode;
			int count = 1;
			while(count < position-1) {
				previousNode = previousNode.getNext();
				count++;
			}
			ListNode currentNode = previousNode.getNext();
			nodeToInsert.setNext(currentNode);
			previousNode.setNext(nodeToInsert);
		}
		return headNode;
	}
	
	// 删除链表的结点
	public ListNode deleteNodeFromLinkedList(ListNode headNode, int position) {
		int size = listlength(headNode);
		if (position > size || position < 1) {
			System.out.println("Position of node to delete is invalid,The valid inputs are 1 to "+size);
			return headNode;
		}
		if (position == 1) { // 删除表头结点
			ListNode currentNode = headNode.getNext();
			headNode = null;
			return currentNode;
		} else {			// 删除中间或表尾结点
			ListNode previousNode = headNode;
			int count = 1;
			while(count < position-1) {
				previousNode = previousNode.getNext();
				count++;
			}
			ListNode currentNode = previousNode.getNext();
			previousNode.setNext(currentNode.getNext());
			currentNode = null;
		}
		return headNode;
	}
	
	// 删除链表
	public void deleteLinkedList(ListNode head) {
		ListNode auxiliaryNode, iterator = head;
		while(iterator != null) {
			auxiliaryNode = iterator.getNext();
			iterator = null;			// 在Java中,垃圾回收器自动处理
			iterator = auxiliaryNode;	
		}
	}

双向链表

双向链表:对于表中的一个结点,可以从两个方向进行操作,每个结点有前驱指针和后继指针。

原文地址:https://www.cnblogs.com/minghaiJ/p/10841236.html