链表知识点详解

基础知识

  链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。
  使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
在这里插入图片描述

单向链表

在这里插入图片描述

简介:

  • Data 数据 + Next 指针,组成一个单链表的内存结构 ;
  • 第一个内存结构称为 链头,最后一个内存结构称为 链尾;
  • 链尾的 Next 指针设置为 NULL [指向空];
  • 单链表的遍历方向单一【只能从链头一直遍历到链尾】

java实现

跑一遍代码可以帮助理解

package test;

public class SingleLinkedList {
	private int size;// 链表节点的个数
	private Node headNode;// 头节点

	public SingleLinkedList() {
		size = 0;
		headNode = null;
	}

	// 链表的每个节点类
	private class Node {
		private Object data;// 每个节点的数据
		private Node next;// 每个节点指向下一个节点的连接

		public Node(Object data) {
			this.data = data;
		}
	}

	// 在链表头添加元素
	public Object addHead(Object obj) {
		Node newHead = new Node(obj);
		if (size == 0) {
			headNode = newHead;
		} else {
			newHead.next = headNode;
			headNode = newHead;
		}
		size++;
		return obj;
	}
	
	//在链表尾部添加元素
	public boolean addNodeAtEnd(Object obj) {
		Node endNode=new Node(obj);
		if(size == 0) {
			headNode = endNode;
			return true;
		}
		int tempSize = size;
		Node current = headNode;
		while(tempSize > 0) {
			if(current.next == null) {
				current.next = endNode;
				size++;
				return true;
			}else {
				current = current.next;
				tempSize--;
			}
		}
		return false;
	}

	// 在链表头删除元素
	public Object deleteHead() {
		Object obj = headNode.data;
		headNode = headNode.next;
		size--;
		return obj;
	}

	// 查找指定元素,找到了返回节点Node,找不到返回null
	public Node find(Object obj) {
		Node current = headNode;
		int tempSize = size;
		while (tempSize > 0) {
			if (obj.equals(current.data)) {
				return current;
			} else {
				current = current.next;
			}
			tempSize--;
		}
		return null;
	}

	// 删除指定的元素,删除成功返回true
	public boolean delete(Object value) {
		if (size == 0) {
			return false;
		}
		Node current = headNode;
		Node previous = headNode;
		while (current.data != value) {
			if (current.next == null) {
				return false;
			} else {
				previous = current;
				current = current.next;
			}
		}
		// 如果删除的节点是第一个节点
		if (current == headNode) {
			headNode = current.next;
			size--;
		} else {// 删除的节点不是第一个节点
			previous.next = current.next;
			size--;
		}
		return true;
	}

	// 判断链表是否为空
	public boolean isEmpty() {
		return (size == 0);
	}

	// 显示节点信息
	public void display() {
		if (size > 0) {
			Node node = headNode;
			int tempSize = size;
			if (tempSize == 1) {// 当前链表只有一个节点
				System.out.println("[" + node.data + "]");
				return;
			}
			while (tempSize > 0) {
				if (node.equals(headNode)) {
					System.out.print("[" + node.data + "->");
				} else if (node.next == null) {
					System.out.print(node.data + "]");
				} else {
					System.out.print(node.data + "->");
				}
				node = node.next;
				tempSize--;
			}
			System.out.println();
		} else {// 如果链表一个节点都没有,直接打印[]
			System.out.println("[]");
		}

	}

}

双向链表

简介

在这里插入图片描述

  • Data 数据 + Next 指针 + Prev 指针,组成一个双向链表的内存结构;
  • 第一个内存结构称为 链头,最后一个内存结构称为 链尾;
  • 链头的 Prev 指针设置为 NULL, 链尾的 Next 指针设置为 NULL;
  • Prev 指向的内存结构称为 前驱, Next 指向的内存结构称为 后继;
  • 双向链表的遍历是双向的,即如果把从链头的 Next 一直到链尾的[NULL] 遍历方向定义为正向,那么从链尾的 Prev 一直到链头 [NULL ]遍历方向就是反向;

java实现

跑一遍代码可以帮助理解

package test;

/**
 * 双向链表
 */
public class TwoWayLinkedList {
	private Node headNode;//链表头节点
	private Node tailNode;//链表尾节点
	private int size;//链表长度
	
	private class Node {
		private Object data;
		private Node pre;
		private Node next;
		

		public Node(Object data) {
			this.data = data;
		}
	}
	
	public TwoWayLinkedList() {
		this.headNode = null;
		this.tailNode = null;
		this.size = 0;
	}
	
	//在链表头添加节点
	public void addHead(Object data){
		Node node = new Node(data);
		if(size == 0) {
			headNode = node;
			tailNode = node;
		}else {
			Node temp = headNode;
			headNode = node;
			headNode.next = temp;
			temp.pre = headNode;
		}
		size++;
	}
	//在链表末尾添加节点
	public void addTail(Object data) {
		Node node = new Node(data);
		if(size == 0) {
			headNode = node;
			tailNode = node;
		}else {
			Node temp = tailNode;
			tailNode = node;
			tailNode.pre = temp;
			temp.next = tailNode;
		}
		size ++;
	}
	
	//删除链表头
	public void deleteHead() {
		if(size == 0) {
			return;
		}else if(size == 1) {
			headNode =null;
			tailNode = null;
		}else {
			headNode=headNode.next;
			headNode.pre = null;
		}
		size --;
	}
	//删除链表尾
	public void deleteTail() {
		if(size == 0) {
			return;
		}else if(size == 1) {
			headNode =null;
			tailNode = null;
		}else {
			tailNode = tailNode.pre;
			tailNode.next = null;
		}
		size --;
	}
	
	//找到指定元素
	public void findOneNode(Object data) {
		if(size == 0) {
			return;
		}
		Node current = headNode;
		int tempSize = size;
		while(tempSize >0) {
			if(data.equals(current.data)) {
				System.out.println("找到指定元素。"+data.toString());
				return;
			}
			current = current.next;
			tempSize --;
		}
		
	}
	
	
	
	//显示节点信息
    public void display(){
        if(size >0){
            Node node = headNode;
            int tempSize = size;
            if(tempSize == 1){//当前链表只有一个节点
                System.out.println("["+node.data+"]");
                return;
            }
            while(tempSize>0){
                if(node.equals(headNode)){
                    System.out.print("["+node.data+"->");
                }else if(node.next == null){
                    System.out.print(node.data+"]");
                }else{
                    System.out.print(node.data+"->");
                }
                node = node.next;
                tempSize--;
            }
            System.out.println();
        }else{//如果链表一个节点都没有,直接打印[]
            System.out.println("[]");
        }
        
    }
	
}

循环链表

在这里插入图片描述

将单向链表的头尾相接就是单向循环链表,将双向链表的头尾相接就是双向循环链表。



  • 文章是个人知识点整理总结,如有错误和不足之处欢迎指正。
  • 如有疑问、或希望与笔者探讨技术问题(包括但不限于本章内容),欢迎添加笔者微信(o815441)。请备注“探讨技术问题”。欢迎交流、一起进步。

参考文献:

数据结构:链表
Java数据结构和算法(七)——链表

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值