Javaの:データ構造 - リスト

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/qq_43336822/article/details/102532096

単一のリスト

1。ヘッドノードなし単一のリスト:

本体:

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;
        }
      }
    }

方法:
鉛ノードは操作が実行される単一リンクリストではありません、ポインタ文を移動します。TMP = tmp.nextは、操作後の文を記述する必要がありますヘッドノードは、ノードの要素を保持しているので、それをスキップすることができません。

CRUDコードは比較的単純であるので、感心しない、showメソッドの代理を行うためにここに置きます。

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

2。最初のノード単一のリスト:

本体:

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());
    }
 }

:メソッド
単一リンクリスト中の鉛のノードの削除操作を、ポインタ文を移動します。TMP = tmp.nextは、操作の前に文を書く必要がありますヘッドノードのデータが何もフィールドないので、それは、印刷スキップする必要があります。

まだショーの代表を行う方法を置きます。

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

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

3.循環リスト

本体:

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;
    }

方法:
そして上記のように3、エルゴードに、最後のポインタフィールドはヘッドノードに設定されているループの状態を記憶しますtmp.next != head

代表としてメソッドを追加するには:

    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.その他の基本的な単一のリスト

(1)[合併は整然としたまま後、2つの命じたリストをマージ]:

考えました:
第一比較LIST1、二つのリストのヘッダに合わせnewListヘッドノードとしてLIST2小の第1のノード要素のサイズは、小さいと、別の比較の素子サイズの後、サイクル条件と同時に空ではありません新しいテーブルポインタの後に、古いヘッダをバックに移動させながら、他は移動しません。これは、他のif文Aです。

コードの実装:

 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:
あなたがのcompareTo()メソッドは、TがComparableを拡張した後、その方法書にあるように、比較的要素である使用したいので、それは言うことです:消去されていないときに徹底的にこすり、同等そここする、私はその方法を使用してみましょう〜

tips2:
一般的な経験のために少し混沌とした独自のコードを書くとき、私はメソッド宣言の順序を記述する方法がわからない、正しい順序は次のようになります。pubic <T> 返回值 方法名(){}

(2)出力リスト要素を[逆]:

考えました:
それは単純な再帰で達成することができます。reversePrintメソッドにランタイム層は、それぞれの層は、前の印刷には、この復帰はデータがこれを下るを続け、復帰後にif文の中に(ヘッドポインタがNULLである)最後の層まで、最後には行きませんでした層の方法は、通常のリターンの終わりとみなされ、その後、元のエントリレベルに戻るまで......印刷データを下ります。最終出力は逆の順序です。

コードの実装:

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

    }

(3)[リスト]逆行

考えました:
通常、一時的なポインタCURに加えて3つのポインタ、すなわち設定、さらに、現在のポインタPポインタの前に設けられている、次のポインタ現在のポインタの現在のポインタが空で循環条件ではないの後、各サイクルであろう点pの間、CURは振り向い。

コードの実装:

   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)最後から二番目のシングルリンクリストにおけるk番目のノードを見つけるために]。

考えました:
k番目のノードおよび最後のノード点の差添え字K -1-逆数、場合には、二つのポインタ、ポインタP1行くステップk-1、及び、別の出発点を確立することが可能であると同時に、ヘッドポインタP2を前進しますp1.nextが空で、p2は最後から二番目のk個のノードに来ます。
図:
ここに画像を挿入説明

コードの実装:

    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)[リンクされたリスト内の2つのノード間の交差を見つける]:
同じノードのアドレスをメモし、だけでなくデータとして

考えました:
最も簡単な考えられる2つの入れ子ループが、時間複雑度はO(n ^ 2)に到達します。
そして、あなたは比較的ポップ後に高度なスタックを活用することができると思うが、それはまた、追加の領域の複雑さのために支払うことになる:O(n)と、より複雑な、長いコードを。
まああきらめる
実際には、長いリストは、あなただけのサイクルを達成することができ、同じ長さの2つのリストは、カットオフしてからトラバースすることができます。
図:
ここに画像を挿入説明
コードの実装:

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:
パブリック・ノード試験クラスで確立するとき、パブリックノードが横断LIST1 P1は、端部P2、p2.next = P1、それによって横断LIST2。

(6)指定されたノードの前に新しいノードを挿入します。]:
考えました:
指定された最初のノードが挿入され、2つの交換ノードされた後。

コードの実装:

 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)リストをリングがある場合、リングノードを与えるために]。
考えました:
遊び場で実行している2人がいる想像して、二人は直線軌道を実行している場合、今、遠く離れて脂肪の家からだけで充電が、円形トラックならば、今将来的に充電するためにバインドされ、今、担当脂肪の家です再び脂肪よりも、家の中でいくつかの点で。
だから我々は、ポインタの二つの異なる速度を設定することができ、ステップはポインタP1脂肪家、充電電流ポインタP2のステップ2、ある瞬間のP1、同じノードへのP2点があれば、そのリンクリストリングは確かにあります。
また、容易にノードが満たすために再度指し、円の周りにリングを終了ときに、2つのノードポインタは確かに、我々はTMPポインタトラバーサルを提供しているカウンタ、カウンタ++、TMPに応じて、長さがリングノードの1つを満たしていることを認識するカウンタ値に等しいです。
胴回り値に使用することは何ですか?もちろん、次の問題を解決するためです。
ベルトループ鎖が延伸前に、リングノードはまた、最後から二番目の長ノードとして見ることができ、そして今、我々は[に従ってできK最後から二番目のノードでの単一のリストを見つける考え、設定2つの出発点は、長さが異なります】ポインタ、彼らは同時に移動するように、まだ始まったばかりしなければならないバックリングポインタに、円の中に現在のポインタの表面仕上げとなるよう、常にそれらの間の5の違いを保証します。この時点P1で、リングにP2点は、ノードが、サイクルの終了、現在のP1の条件は、環上のP2は、ノードアドレスを保持することを条件とします。
図:
ここに画像を挿入説明
コードの実装:

    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;
    }

第二に、二重にリンクされたリスト

二重にリンクされたリストは、唯一の唯一の属性単鎖前駆体に基づいて増加し、かつ操作はそれだけでコードを配置するために、詳細に説明しないが、実質的に同一の単一のリストである:
1。非環式二重リンクリスト:

本体:

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;
    }
 }

方法:

    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。循環二重リンクリスト:

本体:

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;
    }
}

方法:

    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;
    }

おすすめ

転載: blog.csdn.net/qq_43336822/article/details/102532096