算法与数据结构——链表

存储结构

 顺序存储:地址连续,用数组 
 链式存储:地址不连续,用指针(引用,面向对象)

链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域(需要用到的实际数据data),另一个是存储下一个结点地址的指针域;即数据域和指针域;而双向链表中,每个结点包括存储其上一个结点地址的指针,用到的数据data和存储下一个结点的指针。数据结构中的每一个数据结点对应于一个存储单元,这种储存单元称为储存结点,也可简称结点。
————————————————

data为实际存放的数据,next为存放下一个结点地址的指针
单向链表结点结构
在这里插入图片描述

prev是存放上一个结点地址的指针,data为实际用到的数据,next为存放下一个结点地址的指针
双向链表结点结构
双链表

单链表实现代码

public class LinkedList {
    
    
	private Node first;//定义头节点
	private int nItems;//定义单链表中实际的数据的数目
	
	//初始化
	public LinkedList() {
    
    
		this.first = null;
		this.nItems = 0;
	}
	
	//添加头节点
	public void addFirst(int data) {
    
    
		//新建节点
		Node newNode = new Node(data);
		//将新节点的下一个节点指向旧的头节点
		newNode.next = first;
		//将新节点设为头节点
		first = newNode;
		
		nItems ++;
	}
	
	//删除头结点
	public boolean deleteFirst() {
    
    
		//判断链表是否为空
		if(isEmpty()) {
    
    
			System.out.println("链表为空!");
			return false;
		}
		first = first.next;
		nItems --;
		return true;
	}
	
	//有序链表的插入,这样简单排序就可以用链表来实现,复杂度为O(N)
	public void add(int data) {
    
    
		//创建新节点
		Node newNode = new Node(data);
		//创建要插入节点之前的节点
		Node previous = null;
		//创建要插入节点的位置上原来的节点
		Node current = first;
		//按从小到大的顺序排序
		while(current != null && data > current.data) {
    
    
			previous = current;
			current = current.next;
		}
		if(previous == null) {
    
    
			first = newNode; 
		}else {
    
    
			previous.next = newNode;
		}
		newNode.next = current;
		nItems ++;
	}
	
	//查询某个特定值的节点
	public Node findNode(int data) {
    
    
		//定义一个新节点用于查询
		Node current = first;
		while(current != null && current.data != data) {
    
    
			if(current.next == null) {
    
    
				System.out.println("该节点不存在");
				return null;
			}
			current = current.next;
		}
		return current;
	}
	
	//删除某个特定值的节点,并返回该节点
	public Node deleteNode(int data) {
    
    
		//定义被删除节点之前的节点
		Node previous = null;
		//定义被删除的节点
		Node current = first;
		while(current != null && current.data != data) {
    
    
			if(current.next == null) {
    
    
				System.out.println("该节点不存在");
				return null;
			}
			previous = current;
			current = current.next;
		}
		if(previous == null) {
    
    
			first = first.next;
		}else {
    
    
			previous.next = current.next;
		}
		nItems --;
		return current;
	}
	
	//遍历链表
	public void traverseList() {
    
    
		//定义一个节点用于遍历
		Node current = first;
		//判断链表是否为空
		if(current == null) {
    
    
			System.out.println("链表为空!");
			return;
		}
		while(current != null) {
    
    
			System.out.println(current.data);
			current = current.next;
		}
	}
	
	//链表的长度
	public int size() {
    
    
		return nItems;
	}
	
	//判断链表是否为空
	public boolean isEmpty() {
    
    
		return first == null;
	}
	
}
//定义节点
class Node{
    
    
	//声明为public,方便存取
	//指向下一个节点
	public Node next;
	//数据域
	public int data;
	
	public Node(int data) {
    
    
		this.data = data;
	}
}

双链表实现代码

public class DoubleLinkedList {
    
    
	//声明为public,方便存取
	//头指针
	public Node first;
	//尾指针
	public Node last;
	//链表中实际存储的数据的数目
	public int size;
	
	//初始化
	public DoubleLinkedList() {
    
    
		this.first = null;
		this.last = null;
		this.size = 0;
	}
	
	//得到链表容量
	public int size() {
    
    
		return size;
	}
	
	//判断链表是否为空
	public boolean isEmpty() {
    
    
		return size == 0;
	}
	
	//添加头节点
	public void addFirst(int data) {
    
    
		//创建新节点
		Node newNode = new Node(data);
		//判断链表是否为空
		if(isEmpty()) {
    
    
			last = newNode;
		}else {
    
    
			first.previous = newNode;
			newNode.next = first;
		}
		first = newNode;
		size ++;
	}
	
	//添加尾节点
	public void addLast(int data) {
    
    
		//创建新节点
		Node newNode = new Node(data);
		//判断链表是否为空
		if(isEmpty()) {
    
    
			first = newNode;
		}else {
    
    
			last.next = newNode;
			newNode.previous = last;
		}
		last = newNode;
		size ++;
	}
	
	//删除头结点,并返回头结点
	public Node deleteFirst() {
    
    
		if(isEmpty()) {
    
    
			System.out.println("链表为空!");
			return null;
		}
		Node temp = first;
		if(size == 1) {
    
    
			//如果链表中只有一个元素
			last = null;
		}else {
    
    
			first.next.previous = null;
		}
		first = first.next;
		size --;
		return temp;
	}
	
	//删除尾节点,并返回尾节点
	public Node deleteLast() {
    
    
		if(isEmpty()) {
    
    
			System.out.println("链表为空!");
			return null;
		}
		Node temp = last;
		if(size == 1) {
    
    
			//如果只有一个元素
			first = null;
		}else {
    
    
			last.previous.next = null;
		}
		last = last.previous;
		size --;
		return temp;
	}
	
	//将节点插入到指定值为key的节点后面
	public void insert(int key,int value) {
    
    
		//创建要插入的新节点
		Node newNode = new Node(value);
		//创建要插入节点位置上原来的节点
		Node current = first;
		if(isEmpty()) {
    
    
			System.out.println("没有值为" + key + "的值!");
			return;
		}
		while(current.data != key) {
    
    
			if(current == null) {
    
    
				System.out.println("没有值为" + key + "的值!");
				return;
			}
			//往下遍历
			current = current.next;
		}
		current.next.previous = newNode;
		newNode.next = current.next;
		current.next = newNode;
		newNode.previous = current;
		size ++;
	}
	
	//删除特定的节点,并返回该节点
	public Node deleteNode(int value) {
    
    
		if(isEmpty()) {
    
    
			System.out.println("没有值为" + value + "的值!");
		}
		//创建要删除节点
		Node current = first;
		while(current.data != value) {
    
    
			if(current == null) {
    
    
				System.out.println("没有值为" + value + "的值!");
			}
			//继续向下遍历
			current = current.next;
		}
		//如果要删除的节点为首节点
		if(current == first) {
    
    
			deleteFirst();
		}else if(current == last) {
    
    
			//如果要删除的节点为尾节点
			deleteLast();
		}else {
    
    
			current.previous.next = current.next;
			current.next.previous = current.previous;
		}
		size --;
		return current;
	}
	
	
	//正向遍历链表
	public void traverseForward() {
    
    
		Node current = first;
		while(current != null) {
    
    
			System.out.println(current.data);
			current = current.next;
		}
	}
	//反向遍历链表
	public void traverseBackwrad() {
    
    
		Node current = last;
		while(current != null) {
    
    
			System.out.println(current.data);
			current = current.previous;
		}
	}
}
class Node{
    
    
	//声明为public,方便存取
	//指向前一个节点
	public Node previous;
	//指向后一个节点
	public Node next;
	//数据域
	public int data;
	
	public Node(int data) {
    
    
		this.data = data;
	}
}
————————————————

代码参考这里

猜你喜欢

转载自blog.csdn.net/qq_47917118/article/details/114983730