链表的实现(Linked List)

Posted You295

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表的实现(Linked List)相关的知识,希望对你有一定的参考价值。

链表的概念

是一种在物理上非连续、非顺序的数据结构,由若干个节点(node)所组成。

优缺点

优点:真正的动态,不需要处理固定容量的问题
缺点:丧失了随机访问的能力

链表与数组的对比

数组最好用于索引有语意,优点为支持快速查询
链表不适用与索引有语意的情况,优点:动态

构成以及基本功能底层的实现

1)底层创建节点

public class Node {
	public Object data;
	public Node next;

	public Node() {

	}

	public Node(Object data, Node next) {

		this.data = data;
		this.next = next;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

	public Node getNext() {
		return next;
	}

	public void setNext(Node next) {
		this.next = next;
	}

	@Override
	public String toString() {
		return "Node [data=" + data + ", next=" + next + "]";
	}

}

2)底层实现链表头插法:

public class MyLinkedList {
	public Node head; // 头结点
	public int size;

	/**
	 * 头插法
	 * 
	 * @param data
	 */

	public void addFirst(Object data) {
		final Node newNode = new Node(data, null); // 定义节点

		if (head == null) { // 空链表
			head = newNode;
		} else {
			newNode.next = head;
			head = null;
			head = newNode;
		}
		size++;
	}

测试:

public static void main(String[] args) {
		MyLinkedList list = new MyLinkedList();
		list.addFirst(1);
		list.addFirst(2);
		list.addFirst(3);
		System.out.println(list);
		
//输出>>MyLinkedList [head=Node [data=3, next=Node [data=2, next=Node [data=1, next=null]]], size=3]

3)尾插实现:

/**
	 * 尾插法
	 */
	public void addLast(Object data) {
		final Node newNode = new Node(data, null); // 定义节点

		if (head == null) { // 空链表
			head = newNode;
		} else {
			Node p = head;
			while (p.next != null) {
				p = p.next; // 遍历扫描到尾端
			}
			p.next = newNode; // 尾端插入
		}
		size++;
	}

测试:

public static void main(String[] args) {
		MyLinkedList list = new MyLinkedList();

		list.addLast(1);
		list.addLast(2);
		list.addLast(3);
		System.out.println(list);
		
	//输出>>>MyLinkedList [head=Node [data=1, next=Node [data=2, next=Node [data=3, next=null]]], size=3]
	

4)底层实现找到链表的中间节点(快慢引用法):

public void halfNodeTest() {

		MyLinkedList list = new MyLinkedList();

		list.addLast(1);
		list.addLast(2);
		list.addLast(3);
		list.addLast(4);
		list.addLast(5);
		list.addLast(6);
		list.addLast(7);
		System.out.println(halfNode(list.head).data);
	}

	private static Node halfNode(Node head) { // 找到链表的中间位置,利用双指针法
		Node left = head; // 慢指针
		Node right = head; // 快指针

		while (right != null && left.next != null) {
			right = right.next.next;
			left = left.next;
		}
		return left;
	}

}

5)指针法判断链表节点个数的奇偶性

/**
	 * 判断链表个数的奇偶性
	 */

	@Test
	public void test() {
		MyLinkedList list = new MyLinkedList();
		list.addLast(1);
		list.addLast(2);
		list.addLast(3);
		list.addLast(4);
		list.addLast(5);
		list.addLast(6);

		OddOrEven(list.head);
		
		//输出>>>偶数个
	}

	private void OddOrEven(Node head) {
		Node right = head;

		try {
			while (right.next != null) {
				right = right.next.next; // 指针以两倍速度去跑
			}
			System.out.println("奇数个");
		} catch (Exception e) {
			System.out.println("偶数个");
		}
	}

6)根据指定位置去插入元素

/**
	 * 指定位置去插入元素
	 */

	public void addList(Object data, int index) {
		if (index == 0) {
			addFirst(data); // 当在0位置插入,直接调用前插
		} else if (index == this.size) {
			addLast(data); // 当在末尾位置插入,直接调用尾插
		} else {
			Node p = head;
			Node newNode = new Node(data, null);
			for (int i = 0; i < index - 1; i++) { // 找到指定位置的前一个位置
				p = p.next;
			}
			newNode.next = p.next; // 连接操作
			p.next = newNode;
		}
		size++;
	}

测试;

@Test
	public void test01() {
		MyLinkedList list = new MyLinkedList();
		list.addLast(1);
		list.addLast(2);
		list.addLast(3);
		list.addLast(4);
		list.addLast(5);
		list.addLast(6);
		
		list.print();
		System.out.println(">>>>>>>>>>>");
		list.addList(99, 3);
		list.print();
	}

在这里插入图片描述
7)根据index找到元素位置

/**
	 * 根据index找到位置
	 */
	
      public Node findNode(int index) {
    	  Node p = head;
    	  for(int i=0;i<index;i++) { //利用循环遍历
    		  p = p.next;
    	  }
    	  return p;
      }

测试:

/**
	 * 测试根据index找到位置
	 */
	
	@Test
	public void test02() {
		MyLinkedList list = new MyLinkedList();
		list.addLast(1);
		list.addLast(2);
		list.addLast(3);
		list.addLast(4);
		list.addLast(5);
		list.addLast(6);
		
		System.out.println(list.findNode(3).data);
	}
	
	//输出>>>4

8)删除元素

/**
       * 删除元素
       */
      public void remove(int index) {
    	  if(index==0) {  //删除头结点
    		  final Node p = head.next;
    		  head.next = null;
    		  head = p;
    	  }else if(index==(this.size-1)) {  //删除尾结点
    		  Node p = findNode(size-2); //找到倒数第二个节点
    		  p.next = null;
    	  }else {
    		  Node p = findNode(index-1);//找到删除位置的前一个位置
    		  Node after = p.next.next;
    		  p.next = after;
    	  }
    	  
      }

测试:

/**
	 * 测试删除元素
	 */
	@Test
	public void test03() {
		MyLinkedList list = new MyLinkedList();
		list.addLast(1);
		list.addLast(2);
		list.addLast(3);
		list.addLast(4);
		list.addLast(5);
		list.addLast(6);
		
		list.print();
		System.out.println(">>>>>>>>>");
		list.remove(2);
		list.print();
	}

在这里插入图片描述

以上是关于链表的实现(Linked List)的主要内容,如果未能解决你的问题,请参考以下文章

链表 (Linked List)

链表(Linked List): 单链表

Python实现单向有序链表(Singly linked list)

异或链表(XOR Linked List)

876. (Middle of the Linked List)链表的中间结点

Leetcode 237. Delete Node in a Linked List-删除链表的指定节点,不给链表的头节点