刚刚走上工作岗位,准备复习一下之前学过的数据结构和算法,把在北邮和国大学过的知识梳理一下,想想之前并没有用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;
}
}