Java实现数据结构与算法-链表与双向链表

刚刚走上工作岗位,准备复习一下之前学过的数据结构和算法,把在北邮和国大学过的知识梳理一下,想想之前并没有用Java实现过数据结构和算法,之前只用的C。之后工作大部分就与Java打交道了,而且还会接触云计算还有数据挖掘什么的。所以,在这里献一下丑,用Java实现一些基本的和复杂的数据结构还有算法,希望大家多多指正啦!

1.链表:

我的理解,链表相较于普通数组的优势主要在于插入和删除一个节点比较快,时间复杂度在O(1)~O(n)之间(若随机插入,复杂度为O(1),若指定位置插入,复杂度为O(n)),但是,查找一个节点或者访问特定编号的节点则需要O(n)的时间。实现链表,基本的就是实现链表创建,链表节点查找,删除,插入。

/**
 * @author Hash.Zhang
 *
 */
public class LinkedList {

	public LinkedListNode head=new LinkedListNode(0);//set up the head node for the list, but the list does not contain the head node
	private int count=0;//the count of the nodes within the list, set private to prevent accessed by other classes
	/**
	 * the getter of the count of nodes within the list
	 */
	public int getcount()
	{
		return count;
	}
	/**
	 * insert a node(Content_para) after the node at (position), if position is 0, it means insert a new node Content_para after the head node 
	 */
	public boolean insertbehind(int position,LinkedListNode Content_para)
	{
		//Judge if the position is valid
		if(position>count)
		{
			System.out.println("Invalid position! Cannot be inserted!");
			return false;
		}
		LinkedListNode p=getNode(position,false);
		Content_para.Node_next=p.Node_next;
		p.Node_next=Content_para;
		count++;
		return true;
	}
	/**
	 * get the node at (position)
	 * @param flag -> if the flag is true, it is called by users for inserting a new node, it should be judged whether the position is valid
	 * 			   -> if the flag is false, it is called by other inner methods such as insertbehind and delete, the position is bound to be valid
	 */
	public LinkedListNode getNode(int position,boolean flag)
	{
		LinkedListNode p=this.head;
		if(flag&&(position<=0||position>count))
		{
			System.out.println("Invalid position! Cannot be accessed!");
			return null;
		}
		for(int i=0;i<position;i++)
		{
			p=p.Node_next;
		}
		return p;
	}
	/**
	 * delete the node at (position)
	 */
	public boolean deleteNode(int position)
	{
		if(position<=0||position>count)
		{
			System.out.println("Invalid position! Cannot be deleted!");
			return false;
		}
		LinkedListNode p=getNode(position,false),q=getNode(position-1,false);
		p=p.Node_next;
		q.Node_next=p;
		count--;
		return true;
	}
	/**
	 * print the content of the whole list
	 */
	public void printList()
	{
		LinkedListNode p=this.head.Node_next;
		while(p!=null)
		{
			System.out.print(p.Node_Content+" ");
			p=p.Node_next;
		}
		System.out.println();
	}
	/**
	 * the main methods test the LinkedList
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		LinkedList lp=new LinkedList();
		//insert 0~9 to the corresponding position, the list should be 0 1 2 3 4 5 6 7 8 9
		for(int i=0;i<10;i++)
		{
			lp.insertbehind(i,new LinkedListNode(i));
		}
		lp.printList();
		//insert 6 after the first node, the list should be 0 6 1 2 3 4 5 6 7 8 9
		lp.insertbehind(1,new LinkedListNode(6));
		lp.printList();
		//delete the first node, the list should be 6 1 2 3 4 5 6 7 8 9
		lp.deleteNode(1);
		lp.printList();
		//print the second node, it should be 1
		System.out.println(""+lp.getNode(2,true).Node_Content);
	}

}
class LinkedListNode{
	int Node_Content;
	LinkedListNode Node_next;
	/**
	 * the constructor of a Linked List node with node content and the address of the next code
	 * @param Content_para
	 * the content contained by the node
	 * @param next_Node
	 * the address of the next node
	 */
	public LinkedListNode(int Content_para,LinkedListNode next_Node)
	{
		this.Node_Content=Content_para;
		this.Node_next=next_Node;
	}
	/**
	 * the constructor of a Linked List node when there is no next node
	 * @param Content_para
	 * the content contained by the node
	 */
	public LinkedListNode(int Content_para)
	{
		this.Node_Content=Content_para;
		this.Node_next=null;
	}
}
2. 双向链表: 由于链表的指向性访问复杂度为O(n),所以采用双向链表将复杂度降低至O(logn)

这里的双向链表头结点的previous和next都指向链表同一个节点,如果插入位置为零,则改变头节点指向,都指向新结点。

因此,插入节点时分四种情况:

1. 链表为空

2.插入位置为零

3.位置在前半部分

4.位置在后半部分

/**
 * @author Hash.Zhang
 *
 */
public class DoublyLinkedList {
	DoublyLinkedListNode head=new DoublyLinkedListNode(-1);
	private int count=0;
	
	/**
	 * the getter of the count of nodes within the list
	 */
	public int getcount()
	{
		return count;
	}
	/**
	 * get the node at (position) in forward order
	 */
	public DoublyLinkedListNode forwardgetNode(int position)
	{
		DoublyLinkedListNode p=head.Node_next;
		for(int i=1;i<position;i++)
		{
			p=p.Node_next;
		}
		return p;
	}
	/**
	 * get the node at (position) in backward order
	 */
	public DoublyLinkedListNode backwardgetNode(int position)
	{
		DoublyLinkedListNode p=head.Node_previous;
		for(int i=1;i<position;i++)
		{
			p=p.Node_previous;
		}
		return p;
	}
	/**
	 * insert a new node as the first node within the list, which means changing the head node references.
	 * @param Content_para, the new first node
	 */
	public void changeheadinsert(DoublyLinkedListNode Content_para)
	{
		DoublyLinkedListNode p=head.Node_next;
		Content_para.Node_next=p;
		Content_para.Node_previous=p.Node_previous;
		p.Node_previous.Node_next=Content_para;
		p.Node_previous=Content_para;
		head.Node_next=Content_para;
		head.Node_previous=Content_para;
	}
	/**
	 * insert a new node after the node at (position) in forward order
	 * @param Content_para, the new node
	 * @param position, the position in forward order
	 */
	public void forwardinsert(int position,DoublyLinkedListNode Content_para)
	{
		DoublyLinkedListNode p=forwardgetNode(position),q;
		Content_para.Node_next=p.Node_next;
		Content_para.Node_previous=p;
		q=p.Node_next;
		q.Node_previous=Content_para;
		p.Node_next=Content_para;
	}
	/**
	 * insert a new node after the node at (position) in backward order
	 * @param Content_para, the new node
	 * @param position, the position in backward order
	 */
	public void backwardinsert(int position,DoublyLinkedListNode Content_para)
	{
		DoublyLinkedListNode p=backwardgetNode(position),q;
		Content_para.Node_previous=p.Node_previous;
		Content_para.Node_next=p;
		q=p.Node_previous;
		q.Node_next=Content_para;
		p.Node_previous=Content_para;
	}
	/**
	 * get the node at (position)
	 */
	public DoublyLinkedListNode getNode(int position)
	{
		//judge whether the position is valid
		if(position>count||position<=0)
		{
			System.out.println("Invalid position! Cannot be accessed!");
			return null;
		}
		else if(position<(count/2))
		{
			return forwardgetNode(position);
		}
		else
		{
			return backwardgetNode(count+2-position);
		}
	}
	/**
	 * delete the node at (position)
	 */
	public boolean deleteNode(int position)
	{
		DoublyLinkedListNode p;
		//judge whether the position is valid
		if(position>count||count==0||position<=0)
		{
			System.out.println("Invalid position! Cannot be deleted!");
			return false;
		}
		p=getNode(position);
		p.Node_previous.Node_next=p.Node_next;
		p.Node_next.Node_previous=p.Node_previous;
		if(position==1)
		{
			head.Node_next=p.Node_next;
			head.Node_previous=p.Node_next;
		}
		count--;
		return true;
	}
	/**
	 * insert a new node after the node at (position)
	 */
	public boolean insertbehind(int position,DoublyLinkedListNode Content_para)
	{
		//judge whether the position is valid
		if(position>count||position<0)
		{
			System.out.println("Invalid position! Cannot be inserted!");
			return false;
		}
		//judge whether it is the first node in the list
		else if(count==0)
		{
			head.Node_next=Content_para;
			head.Node_previous=Content_para;
			count++;
			return true;
		}
		//judge whether the first node is changed, if so, perform the changeheadinsert
		else if(position==0)
		{
			changeheadinsert(Content_para);
			count++;
			return true;
		}
		else if(position<(count/2))
		{
			forwardinsert(position,Content_para);
			count++;
			return true;
		}
		else
		{
			backwardinsert(count+1-position,Content_para);
			count++;
			return true;
		}
	}
	/**
	 * print the list in forward order
	 */
	public void forwardprint()
	{
		DoublyLinkedListNode p=head;
		for(int i=0;i<count;i++)
		{
			p=p.Node_next;
			System.out.printf("%4d",p.Node_Content);
		}
		System.out.println("   Net count: "+count+" nodes");
	}
	/**
	 * print the list in backward order
	 */
	public void backwardprint()
	{
		DoublyLinkedListNode p=head;
		for(int i=0;i<count;i++)
		{
			p=p.Node_previous;
			System.out.printf("%4d",p.Node_Content);
		}
		System.out.println("   Net count: "+count+" nodes");
	}
	/**
	 * the main methods test the Doubly Linked List
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		DoublyLinkedList lp=new DoublyLinkedList();
		//insert 0~3 into the list in corresponding position,the list in forward order should be: 0 1 2 3 
		for(int i=0;i<4;i++)
		{
			lp.insertbehind(i,new DoublyLinkedListNode(i));
		}
		lp.forwardprint();
		lp.backwardprint();
		//insert 4 after the second node, the list in forward order should be: 0 1 4 2 3
		lp.insertbehind(2,new DoublyLinkedListNode(4));
		lp.forwardprint();
		lp.backwardprint();
		//print the first to the forth node, they should be 0 1 4 2
		for(int i=1;i<=4;i++)
			System.out.println(lp.getNode(i).Node_Content);
		// delete the first to the second node, the rest in forward order should be 4 2 3
		for(int i=0;i<2;i++)
			lp.deleteNode(1);
		lp.forwardprint();
		lp.backwardprint();
	}
}
class DoublyLinkedListNode{
	int Node_Content;
	DoublyLinkedListNode Node_previous;
	DoublyLinkedListNode Node_next;
	/**
	 * the constructor of a Doubly Linked List node with node content and the address of the next code and the previous node
	 * @param Content_para
	 * the content contained by the node
	 * @param previous_Node
	 * the content contained by the node
	 * @param next_Node
	 * the address of the next node
	 */
	public DoublyLinkedListNode(int Content_para,DoublyLinkedListNode previous_Node,DoublyLinkedListNode next_Node)
	{
		this.Node_Content=Content_para;
		this.Node_previous=previous_Node;
		this.Node_next=next_Node;
	}
	/**
	 * the constructor of a Doubly Linked List node with node content, the references are referred to itself
	 */
	public DoublyLinkedListNode(int Content_para)
	{
		this.Node_Content=Content_para;
		this.Node_previous=this;
		this.Node_next=this;
	}
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值