链表---双向链表的解析与实现

(1)如果为每个节点保留两个引用prvenext,prev指向当前节点的上一个节点,让next指向当前节点的下一个节点。此时链表既可以向前依次访问每个节点,也可以向后依次访问每个节点,这种形式的节点称为双向链表。

(2)双向链表的查找

   因为双向链表既可以向前搜索也可以向后搜索,当被搜索节点更靠近head或者tail中的某一端时,就从那一端开始搜索 index<size/2head开始搜索,index>size/2tail开始搜索

(3)双向链表的插入


(4)双向链表的删除


实现

public class DoubleLinkedList<T>
{
	//节点类
  private class Node
  {
	  //每个节点有三个成员变量 
	  private T data;
	  private Node next;
	  private Node prev;
	  public Node()
	  {}
	  public Node(T data,Node next,Node prev)
	  {
		  this.data = data;
		  this.next = next;
		  this.prev = prev;
	  }
  }
  //分别用来指向链表的头节点、尾节点、保存链表的长度
  private Node head;
  private Node tail;
  private int size;
  
  //链表的构造函数 
  public DoubleLinkedList()
  {
	  head = null;
	  tail = null;
  }
  public DoubleLinkedList(T element)
  {
	  head = new Node(element,null,null);
	  tail = head;
	  size++;
  }
  
  
  //链表的长度
  public int length()
  {
	  return size;
  }
  //查找指定索引处的节点
  private Node getNodeByIndex(int index)
  {
	 if(index < 0 || index > size-1)
	 {
		 throw new IndexOutOfBoundsException("双向链表索引越界");
	 }
	 if(index < size / 2)//如果索引在前半段的位置则从头节点开始遍历
	 {
		 Node current = head;
		 for (int i = 0; i < size / 2 && current != null; i++,current = current.next)
		{
			if(i == index)
			{
				return current;
			}
		}
	 }
	 else
	 {
		 Node current = tail;
		 for (int i = size-1; i > size / 2 && current!= null; i++,current = current.prev)
		{
			if(i == index )
			{
				return current;
			}
		}
	 }
	return null;
  }
  
  //查找指定元素的索引位置
  public int  locateIndexByElement(T element)
  {
	  Node current = head;
	  for (int i = 0; i < size && current != null; i++,current = current.next)
	{
		if(current.data == element)
		{
			return i;
		}
	}
	  return -1;
  }
  
  //插入 将指定的元素插入到指定的位置处
  public void insert(T element,int index)
  {
	  if(index < 0 || index > size )
	  {
		  throw new IndexOutOfBoundsException("双向链表插入索引越界");
	  }
	  
	  if(null == head)
	  {
		add(element); 
	  }
	  else
	  {
		  if(index == 0)
		  {
			  addAtHead(element);
		  }
		  else
		  {
			  Node prev = getNodeByIndex(index-1);//获取要出入位置的前一个节点
			  Node next = prev.next;//第index位置的节点将会变为新节点的下一个节点
			  Node newNode = new Node(element,next,prev);//新节点的前一个节点是prev 后一个节点是next
			   prev.next = newNode;
			   next.prev = newNode;
			   size++;
		  }
	  }
  }
  
//插入  尾差法
  public void  add(T element)
  {
	  if (head == null)
	  {
		 addAtHead(element);
	  }
	  else
	  {
		Node newNode = new Node(element,null,tail);
		tail.next = newNode;
		tail = newNode;
	  }
	  size++;
  }
  
 //插入 头差法
  public void addAtHead(T element)
  {
	
	  	  Node newNode = new Node(element,head,null);
	  	  if(head==null)
	  	  {
	  		head = newNode;
	  		tail = head;
	  	  }
	  	  else
	  	  {
	  		head.prev = newNode;
		  	head = newNode;
	  	  }
	  	  size++;
  }
  
  //删除
  public T delete(int index)
  {
	  if(index < 0 || index > size)
	  {
		  throw new IndexOutOfBoundsException("双向链表插入索引越界");
	  }
	 Node deleteNode;
	  if(index == 0)//若是删除第一个节点 要重新得到头节点
		  {
			  deleteNode = head;
			  head = head.next;//新的头节点的是原来头节点的下一个节点
			  deleteNode.next = null;
		  }
	 else
		{
			Node prev = getNodeByIndex(index-1);//找到要删除节点的前一个节点
			deleteNode = prev.next;//找到要删除的节点
			prev.next = deleteNode.next;//把prev的next指向要删除节点的下一个节点
			if(deleteNode.next != null)
			{
				deleteNode.next.prev = prev;//要删除节点的下一个节点指向的前一个节点是prev
			}
			deleteNode.prev = null;
			deleteNode.next = null;
			
		}
	     size--;
	    return deleteNode.data;
	    
	  }
  //判断链表是否为空
  public boolean isEmpty()
  {
	  return size == 0;
  }
  
  //清空线性变
  
  public void clear()
  {
	  head = null;
	  tail = null;
	  size = 0;
  }
  
  public String toString()
  {
	  if(isEmpty())
	  {
		  return "[]";
	  }
	  else
	  {
		  StringBuilder sb = new StringBuilder("[");
		 
		 for ( Node current = head;current != null; current = current.next)
		 {
			sb.append(current.data.toString() + ",");
		 }
		 int len = sb.length();
		 return sb.delete(len-1,len).append("]").toString();
		
	  }
  }
  
}
测试

public class DoubleLlinkedListTest
{
	public static void main(String[] args)
	{
		DoubleLinkedList<String> list = new DoubleLinkedList<String>();
		list.addAtHead("HELLO");
		list.add("world");
		System.out.println(list);
		list.insert("111",1);
		list.insert("222",1);
		System.out.println(list);
		list.addAtHead("head"); 
		System.out.println(list);
		list.delete(2);
		System.out.println(list);
		list.clear();
		System.out.println(list );
	}

}
结果

[HELLO,world]
[HELLO,222,111,world]
[head,HELLO,222,111,world]
[head,HELLO,111,world]
[]


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值