Java创建一个简单的链表类,实现几个基础操作

Java创建一个简单的链表类,实现几个基础操作

今天下午跟着视频做了一下利用eclipse创建一个简单的双向循环链表,并在在类中写一些基础的方法,实现对链表的增加、插入、删除、输出等操作。这一次只是实现了几个最基础的方法,还有其他的一些方法并没有写出来,如果有错误的欢迎大佬指出~

  1. 先创建节点类
    Java创建一个简单的链表类,实现几个基础操作_第1张图片
public class Node {
     
	Node previous;// 上一个节点
	Node next;// 下一个节点
	Object elem;// 元素数据
	public Node(Node previous, Node next, Object elem) {
     
		super();
		this.previous = previous;
		this.next = next;
		this.elem = elem;
	}
	public Node(Object elem) {
     
		super();
		this.elem = elem;
	}
}

  1. 首先是实现在尾插法创建链表
public void add(E obj){
     
		Node node = new Node(obj);//创建新的节点
		
		if(first==null){
     //如果此时链表为空
			first = node;
			last = node;
		}else{
     //链表不为空
			node.previous = last;
			node.next = first;
			last.next = node;
			last = node;
			first.previous = last;//首尾相连保证循环
		}
		size++;
	}
  1. 根据指定索引获取对应节点的值
    ①在这里由于考虑到需要经常通过索引来获取节点信息,因此将这一部分代码封装成一个单独的方法,以便后面调用方便同时精简代码
public Node getNode(int index){
     
		if(index<0||index>size-1)
			throw new RuntimeException("错误索引:"+index+",索引值不得小于0或大于链表长度!");
		Node temp = first;
		if(index>(size>>1)){
     //如果输入的索引值大于长度的一半,则从后往前遍历
			for(int i=size-1;i>=index;i--){
     
				temp = temp.previous;
			}
		}else{
     //否则从前往后遍历
			for(int i=0;i<index;i++){
     
				temp = temp.next;
			}
		}
		return temp;
	}

②通过调用方法来获取节点对应的值

public E get(int index){
     
		Node temp = getNode(index);
		return (E)temp.elem;
	}

4.在指定的位置插入一个新的元素

	public void insert(int index, E e) {
     
		Node insertNode = new Node(e);
		Node temp = getNode(index);
		if (temp == first) {
     //待插入的位置是链表的第一个节点
			first = insertNode;
			first.next = temp;
			first.previous = last;
			size++;//长度加一
		}else if(temp == last){
     //待插入的节点是链表的最后一个节点
			add(e);//此时操作与直接加入元素时一样,直接调用
		}else{
     //待插入的位置不在端点
			Node preNode = temp.previous;//创建新的节点代表temp的前驱节点
			preNode.next = insertNode;
			insertNode.previous = preNode;
			temp.previous = insertNode;
			insertNode.next = temp;
			size++;
		}
	}
  1. 删除指定的索引的节点信息
//根据指定索引删除节点
	public void remove(int index) {
     
		Node temp = getNode(index);
		if (temp == last) {
     //如果删除的节点是链表的最后一个节点
			last = temp.previous;//将last标志前移一个位置
			last.next = first;//将last的后继指向第一个节点,连成循环
			first.previous = last;//将first的前驱指向最后一个节点
			temp.previous = temp.next = null;//置空删除
		}
		else if(temp == first) {
     //如果删除的节点是链表的第一个节点
			first = temp.next;//将first标志后移一个位置
			last.next = first;//将last的后继指向第一个节点,连成循环
			first.previous = last;//将first的前驱指向最后一个节点
			temp.previous = temp.next = null;//置空删除
		}
		else {
     //如果删除的节点不在链表的两端
			Node preNode = temp.previous;//创建新的节点代表待删除的前驱节点
			Node nextNode = temp.next;//创建新的节点代表待删除的后继节点
			preNode.next = nextNode;
			nextNode.previous = preNode;
			temp.previous = temp.next = null;//置空删除
		}
		size--;//长度-1
	}

在删除节点时一般除了指定索引之外,还可以通过节点值来删除节点

public void remove(E e){
     
		int i=0;
		Node temp = first;
		while(temp.elem!=e){
     //先找到该值在链表中第一次出现的位置
			temp = temp.next;
			i++;
		}
		remove(i);//调用remove(int index)
	}

这个部分是先通过遍历来找到找待删除的节点的索引,然后再调用同名方法来删除
6. 重写toString方法
通过创建一个StringBuilder对象来存放链表的节点值

public String toString() {
     
		StringBuilder sb = new StringBuilder("[");
		Node temp = first;
		for(int i=0;i<size;i++){
     
			sb.append(temp.elem+",");
			temp = temp.next;
		}
		sb.setCharAt(sb.length()-1, ']');
		return sb.toString();
	}
  1. 完整代码
public class setLinkedList<E> {
     
	private Node first;//首节点标志
	private Node last;//尾节点标志
	private  int size;//长度
	
	//获取节点
	public E get(int index){
     
		Node temp = getNode(index);
		return (E)temp.elem;
	}
	
	//为了方便使用,将该部分封装成一个独立的方法,获取指定索引的节点信息
	public Node getNode(int index){
     
		if(index<0||index>size-1)
			throw new RuntimeException("错误索引:"+index+",索引值不得小于0或大于链表长度!");
		Node temp = first;
		if(index>(size>>1)){
     //如果输入的索引值大于长度的一半,则从后往前遍历
			for(int i=size-1;i>=index;i--){
     
				temp = temp.previous;
			}
		}else{
     //否则从前往后遍历
			for(int i=0;i<index;i++){
     
				temp = temp.next;
			}
		}
		return temp;
	}
	
	//尾插法添加元素
	public void add(E obj){
     
		Node node = new Node(obj);//创建新的节点
		
		if(first==null){
     //如果此时链表为空
			first = node;
			last = node;
		}else{
     //链表不为空
			node.previous = last;
			node.next = first;
			last.next = node;
			last = node;
			first.previous = last;//首尾相连保证循环
		}
		size++;
	}
	
	// 指定位置插入节点
	public void insert(int index, E e) {
     
		Node insertNode = new Node(e);
		Node temp = getNode(index);
		if (temp == first) {
     //待插入的位置是链表的第一个节点
			first = insertNode;
			first.next = temp;
			first.previous = last;
			size++;//长度加一
		}else if(temp == last){
     //待插入的节点是链表的最后一个节点
			add(e);//此时操作与直接加入元素时一样,直接调用
		}else{
     //待插入的位置不在端点
			Node preNode = temp.previous;//创建新的节点代表temp的前驱节点
			preNode.next = insertNode;
			insertNode.previous = preNode;
			temp.previous = insertNode;
			insertNode.next = temp;
			size++;
			
		}

	}
	
	//根据指定索引删除节点
	public void remove(int index) {
     
		Node temp = getNode(index);
		if (temp == last) {
     //如果删除的节点是链表的最后一个节点
			last = temp.previous;//将last标志前移一个位置
			last.next = first;//将last的后继指向第一个节点,连成循环
			first.previous = last;//将first的前驱指向最后一个节点
			temp.previous = temp.next = null;//置空删除
		}
		else if(temp == first) {
     //如果删除的节点是链表的第一个节点
			first = temp.next;//将first标志后移一个位置
			last.next = first;//将last的后继指向第一个节点,连成循环
			first.previous = last;//将first的前驱指向最后一个节点
			temp.previous = temp.next = null;//置空删除
		}
		else {
     //如果删除的节点不在链表的两端
			Node preNode = temp.previous;//创建新的节点代表待删除的前驱节点
			Node nextNode = temp.next;//创建新的节点代表待删除的后继节点
			preNode.next = nextNode;
			nextNode.previous = preNode;
			temp.previous = temp.next = null;//置空删除
		}
		size--;//长度-1
	}
	
	//从链表中删除指定值
	public void remove(E e){
     
		int i=0;
		Node temp = first;
		while(temp.elem!=e){
     //先找到该值在链表中第一次出现的位置
			temp = temp.next;
			i++;
		}
		remove(i);//调用remove(int index)
	}
	
	@Override
	//重写tostring方法
	public String toString() {
     
		StringBuilder sb = new StringBuilder("[");
		Node temp = first;
		for(int i=0;i<size;i++){
     
			sb.append(temp.elem+",");
			temp = temp.next;
		}
		sb.setCharAt(sb.length()-1, ']');
		return sb.toString();
	}
	
	public static void main(String[] args) {
     
		setLinkedList<String> list = new setLinkedList<>();
		try {
     
			list.add("a");
			list.add("b");
			System.out.println(list);
		} catch (RuntimeException e) {
     
			System.out.println(e);
		}
	}
}

输出结果为:Java创建一个简单的链表类,实现几个基础操作_第2张图片
8.总结
在写这个双向链表的时候,由于是将首尾相连形成一个循环的链表,因此在写插入、删除等涉及索引的方法时,没有考虑到待操作的节点如果是首尾节点时的操作方式与不是首尾节点时的操作方式不同。所以调式的时候总是报错,最后才意识到这个问题。
这一次只是实现了一些小小的功能,还有很多没有实现。在已经实现了的方法中,如果有错误的,还麻烦各位大佬指正一下,谢谢啦!

你可能感兴趣的:(java,链表)