Java: Data structure - list

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/qq_43336822/article/details/102532096

A single list

1.Without head nodeThe single list:

main body:

public class LianBiaowithoutHead <E> {

    protected Node<E> head;			//声明第一个结点(并不是头结点)

    class Node<E>{					//创建内部类Node
        protected E element;	
        protected Node<E> next;

        public Node(E data){
            this.element = data;
        }
      }
    }

Method:
When the lead node is not a single linked list operation is performed,Move the pointer statement: tmp = tmp.next need to write a statement after the operation, Because the head node holds an element of a node, it can not be skipped.

CRUD code is relatively simple and so does not impress, put here to do a show method behalf.

	public void show(){
	 	Node<E> tmp = head;
        while(tmp != null){
            System.out.print(tmp.element+" ");
            tmp = tmp.next;    //注意在操作语句之后移动tmp,否则会跳过第一个结点,而这里的head是放有数据的
        }
        System.out.println();
	}

2.First NodeThe single list:

main body:

public class LianBiaowithHead <E>{
    protected Node <E> head;

    class Node<E>{
        protected E element;
        protected Node<E> next;

        public Node(E data){
            this.element = data;
        }
    }

    public LianBiaowithHead(){ //需要创立头结点
        head = new Node<>((E)new Object());
    }
 }

: Method
When the lead node during a single linked list delete operation,Move the pointer statement: tmp = tmp.next need to write a statement before the operation, Because the head node data fields nothing, then it needs to be skipped printed.

Still put way to do a show representative.

    public void show(){
        Node<E> tmp = head;

        while(tmp.next != null){
            tmp = tmp.next;      //跳过头结点打印
            System.out.print(tmp.element + " ");
        }
        System.out.println();
    }

3. circular list

main body:

public class CircleList<E> {//循环单链表(带头结点)

    protected Node<E> head;

    class Node <E>{
        protected E element;
        protected Node<E> next;

        public Node(E data){
            this.element = data;
        }


    }

    public CircleList(){
        this.head = new Node<>((E)new Object());
        head.next = head;
    }

Method:
and 3 as above, will remember the last pointer field is set to a head node, loop condition into ergodictmp.next != head

To add a method as a representative:

    public void addTail(E data){
        Node<E> n = new Node<E>(data);
        Node<E> tmp= head;
        while(tmp.next != head){
            tmp = tmp.next;
        }
        n.next = tmp.next;
        tmp.next = n;
    }

4. Other basic single list

(1) [merge two ordered lists, after the merger remains orderly]:

thought:
List1 first comparison, the size of the first node element of list2 small as combined newList head node, to the header of the two lists is not empty at the same time as the cycle conditions, after another comparison element size, with the small after the new table pointer, while moving back the old header, the other does not move. That is, a if else statements.

Code:

 public <E extends Comparable<E>> Node<E> mergeList(Node<E> head1,Node<E> head2){ 
        Node<E> tmp = null;
        Node<E> curHead;

        if(head1.element.compareTo(head2.element) <0){
            curHead = head1;
            head1 = head1.next;  //别忘了这个的表头要往后移一个
        }
        else {
            curHead = head2;
            head2 = head2.next;
        }
        tmp = curHead;
        while(head1!= null  && head2!= null){
            if(head1.element.compareTo(head2.element)<0){
                tmp.next =head1;
                head1 = head1.next;
            }
            else{
                tmp.next = head2;
                head2 = head2.next;

            }
            tmp = tmp.next;
    }
        if(head1 == null){
            tmp.next = head2;
        }
        if(head2 == null){
            tmp.next = head1;
        }

        return curHead;
    }

Tips1:
Because you want to use compareTo () method is relatively element, so to be in the method statement after the T extends Comparable, that is to say: when not erased so thoroughly rub, rub there Comparable, let me use its methods ~

tips2:
When writing your own code for a generic experience a bit chaotic, I do not know how to write the order of the method declaration, the correct order should be:pubic <T> 返回值 方法名(){}

(2) [reverse] output list element:

thought:
It can be achieved with a simple recursive. Runtime layers into reversePrint method, each layer did not go in the end, until the last layer (head pointer is NULL) into the if statement after the return, this return to the previous print data continue to go down this layer method considered the end of the normal return and then go down ...... print data until the return to the original entry level. The final output is the reverse order.

Code:

    public static <E> void reversePrint(LianBiaowithoutHead<E>.Node<E> head){
        if(head == null)
            return;
        reversePrint(head.next);
        System.out.print(head.element + " ");

    }

(3) [list] Retrograde :

thought:
Setting three pointers, i.e. in addition to ordinary temporary pointer cur, is additionally provided before the current pointer p a pointer, a pointer to next after the current pointer to the current pointer is not empty circulating conditions, each cycle will be between the points p, cur turned around.

Code:

   public Node<E> reverseList(Node<E> head){ 
        Node <E> cur = head;
        Node <E> p = null;
        Node <E> newHead =null;

        while(cur!= null){
            Node<E> next = cur.next;
            if(next == null)
                newHead = cur;
            cur.next = p;
            p = cur;
            cur = next;
        }

        return newHead;
    }

(4) [in the penultimate single linked list to find the k-th node]:

thought:
Reciprocal k-th node and the last node point difference subscript k-1-, it is possible to establish two pointers, a pointer p1 go step k-1, and then another starting point and simultaneously advancing the head pointer p2, when p1.next is empty, p2 will come to the penultimate k nodes.
Figure:
Here Insert Picture Description

Code:

    public E findTheK(int index){

        if(head == null || index<0)
            return null;
        Node<E> p1 = head;
        Node<E> p2 = head;
        int num = 0;

        while (num != index-1){
            p2 = p2.next;
            num++;
        }

        while(p2.next != null){
            p1 = p1.next;
            p2 = p2.next;
        }

        return p1.element;

    }

(5) [find the intersection between two nodes in a linked list]:
note the address of the same node, and not just as a data

thought:
The easiest conceivable two nested loops, but to reach the time complexity O (n ^ 2) ,.
And then think you can take advantage of the advanced stack after a relatively pop, but it will also pay for additional space complexity: O (n), and more complex, long code.
Well give up
in fact, a long list could be cut off, the two lists of the same length and then traverse, you can only achieve a cycle.
Figure:
Here Insert Picture Description
Code:

public static <E> LianBiaowithHead<E>.Node<E> banana(LianBiaowithHead<E> list1 , LianBiaowithHead<E> list2){

        if(list1.head == null || list2.head == null) return null;

        int length1 = list1.getLength();
        int length2 = list2.getLength();
        int lengthDif = Math.abs(length1-length2);

        LianBiaowithHead<E>.Node<E> longHead = list1.head;
        LianBiaowithHead<E>.Node<E> shortHead = list2.head;

        if(length1 < length2){
            longHead = list2.head;;
            shortHead = list1.head;
        }

        for(int i=0; i<lengthDif; i++){
            longHead = longHead.next;
        }

        while(longHead != shortHead){
            longHead = longHead.next;
            shortHead = shortHead.next;
        }
        return longHead;
    }

Tips1:
When established in the public node test class, list1 p1 traversed by the public nodes, list2 traversed by the end p2, p2.next = p1 it.

(6) [insert the new node before the specified node.]:
thought:
After the specified first node is inserted, and then two switching nodes.

Code:

 public void LinkedListInsertBefore(Node<E> head, Node<E> pos, E data){//不允许遍历链表,在pos之前插入
        Node<E> n = new Node<>(data);
        Node<E> taxi = head;

        while(taxi.next != head){
            if(taxi.next == pos)
                break;
            taxi = taxi.next;
        }
        taxi.next = n;
        n.next = pos;

    }

(7) [the list if there is a ring, the ring to give the node]:
thought:
Imagine there are two people running in the playground, is a fat house, is now a charge, if two people are running straight track, now charge only from fat house farther away, but if the circular track, is now bound to charge in the future again at some point in the house more than fat.
So we can set two different speed of the pointer, the pointer p1 fat house a step is, the charging current pointer p2 step 2, if there is a certain moment p1, p2 point to the same node, then the linked list there is certainly rings.
Also readily recognize that two node pointers certainly meet one of the ring nodes, in accordance with a counter that we have provided tmp pointer traversal, the counter ++, tmp when finished ring around the circle, again pointing to the nodes meet, length to equal to the counter value.
To girth value what's the use? Of course, in order to solve the next problem.
Before the belt loop chain stretched, the ring nodes also can be seen as the penultimate length nodes, and now we can according to [ find a single list in the penultimate nodes k ] idea, setting two starting points differ by length pointer, so that they move at the same time, guarantee always a difference of 5 between them, so that the current pointer surface finish in a circle, back into the ring pointer must just begun. At this time p1, p2 point to the ring while the node, provided that the conditions for termination of the cycle, current p1, p2 on the ring holds the node address.
Figure:
Here Insert Picture Description
Code:

    public static <E> CircleList<E>.Node<E> isRing(CircleList<E>.Node<E> head){//单链表是否有环,环的入口节点是哪个
        if(head == null)
            return null;
        if(head.next==null)
            return null;

        CircleList<E>.Node<E> taxi1 = head.next;
        CircleList<E>.Node<E> taxi2 = head.next.next;

        while(taxi2 != null && taxi1!=null){
            if(taxi2 == taxi1){
                return taxi1;
            }

            taxi1 = taxi1.next;
            taxi2 = taxi2.next;
            if(taxi2.next != null)//避免空指针异常
                taxi2 = taxi2.next;
        }

        return null;
    }

    public static <E> CircleList<E>.Node<E> ringNode(CircleList<E>.Node<E> head){
        CircleList<E>.Node<E> meet = isRing(head);

        if(meet == null)
            return null;

        int length = 0;
        CircleList<E>.Node<E> tmp = meet;

        do{
            tmp = tmp.next;
            length++;
        }while(tmp != meet);  //得到环的长度

        System.out.println("length of the ring:"+length);

        CircleList<E>.Node<E> p1 = head;
        CircleList<E>.Node<E> p2 = head;
        int num = 0;
        while(num != length){
            num++;
            p2 = p2.next;
        }//p2先走length步

        while( p1 != p2){
            p1 = p1.next;
            p2 = p2.next;
        }

        return p1;
    }

Second, the doubly linked list

Doubly linked list will only increase on the basis of a single chain precursor only attribute, and the operation is substantially the same single list, it will not described in detail, just to put the code:
1.AcyclicDoubly linked list:

main body:

public class DoubleLinkedList<E> {
    protected Node<E> head;

    class Node<E>{
        protected E element;
        protected Node<E> before;
        protected Node<E> after;

        public Node(E data){
            element = data;
        }
    }

    public DoubleLinkedList(){
        this.head = new Node<>((E)new Object());
        head.after = head;
        head.before = head;
    }
 }

method:

    public void addTail(E data){
        Node<E> newNode = new Node<>(data);
        Node<E> tmp = head;

        while(tmp.after != head){
            tmp = tmp.after;
        }
        tmp.after = newNode;
        newNode.before = tmp;
        newNode.after = head;
    }

    public void addHead( E data){
        Node<E> newNode = new Node<>(data);
        Node<E> tmp = head;

        newNode.after = head.after;
        newNode.before = head;
        head.after = newNode;
    }

    public void delete( E data){
        Node<E> tmp = head;

        while(tmp.after != head){
            if(tmp.element.equals(data)){
                tmp.before.after = tmp.after;
                tmp.after.before = tmp.before;
            }else {
                tmp = tmp.after;
            }
        }
    }

    public int getLength(){
        Node<E> tmp = head;
        int size = 0;

        while(tmp.after != head){
            tmp = tmp.after;
            size ++;
        }

        return size;
    }

    public void show(){
        Node<E> tmp = head;

        while(tmp.after != head){
            tmp = tmp.after;
            System.out.print(tmp.element + " ");
        }

        System.out.println();
    }

    public E findValue(int index){
        Node<E> tmp = head;
        int num = 0;

        while(tmp.after != head){ //第一个结点(不是头结点)的下标是0
            if( num == index)
                return tmp.element;
            tmp = tmp.after;
            num ++;
        }

        return null;
    }

2.cycleDoubly linked list:

main body:

public class DoubleCircularLinkedList <E>{

    protected  Node<E> head;

    class Node<E>{
        protected E element;
        protected Node<E> before;
        protected Node<E> after;

        public Node(E data){
            element = data;
        }
    }

    public DoubleCircularLinkedList(){
        this.head = new Node<>((E)new Object());
        head.after = head;
        head.before = head;
    }
}

method:

    public void addTail(E data){
        Node<E> newNode = new Node<>(data);
        Node<E> tmp = head;

        while(tmp.after != head){
            tmp = tmp.after;
        }
        tmp.after = newNode;
        newNode.before = tmp;
        newNode.after = head;
    }

    public void addHead( E data){
        Node<E> newNode = new Node<>(data);
        Node<E> tmp = head;

        newNode.after = head.after;
        newNode.before = head;
        head.after = newNode;
    }

    public void delete( E data){
        Node<E> tmp = head;

        while(tmp.after != head){
            if(tmp.element.equals(data)){
                tmp.before.after = tmp.after;
                tmp.after.before = tmp.before;
            }else {
                tmp = tmp.after;
            }
        }
    }

    public int getLength(){
        Node<E> tmp = head;
        int size = 0;

        while(tmp.after != head){
            tmp = tmp.after;
            size ++;
        }

        return size;
    }

    public void show(){
        Node<E> tmp = head;

        while(tmp.after != head){
            tmp = tmp.after;
            System.out.print(tmp.element + " ");
        }

        System.out.println();
    }

    public E findValue(int index){
        Node<E> tmp = head;
        int num = 0;

        while(tmp.after != head){ //第一个结点(不是头结点)的下标是0
            if( num == index)
                return tmp.element;
            tmp = tmp.after;
            num ++;
        }

        return null;
    }

Guess you like

Origin blog.csdn.net/qq_43336822/article/details/102532096