1. 程式人生 > >java資料結構—單鏈表的實現原理

java資料結構—單鏈表的實現原理

再次學習資料額結構,看到前面的單鏈表,感覺裡面的思路很不錯,自己動手寫程式碼嘗試一下,果然一動手就發現自己並沒有完全理解。這裡主要記錄我花了很長時間才理解的地方,不去考慮增刪改查,我覺得這些功能在很多地方都實現過,不是重點,也有很多資料可查。

單鏈表的原理網上很多,這裡也不解釋,先上程式碼。

這是一個節點類,用於記錄節點內容和物件引用(地址),其中不包含一些基本功能,只寫了必要的函式。

public class Node {
    Object data;//節點包含的具體內容
    Node next;//節點的引用,用於指向下一個節點

    Node (Node i){//建構函式1,用於初始化頭結點
next=i; } Node (Object i,Node j){//建構函式2,用於其他節點。 data=i; next=j; } public void setnext(Node nextval){//這個函式作用是把其他節點的引用指向這個節點。 next=nextval; } public Object getelement(){//獲取節點的內容 return data; } }

這是我第一次做的測試函式

public class main_Node {

    public
static void main(String[] args) { Node head;//頭結點 Node current;//表示當前節點 current=head=new Node(null);//初始化為空 current.setnext(new Node(1,head.next));//新增一個節點 current.setnext(new Node(2,current.next));//新增兩個節點 current.setnext(new Node(3,current.next));//新增三個節點 current=head.next;//讓current表示head的下一個節點,也就是第一個節點。
int a=(int)current.getelement();//獲取該節點的內容 System.out.println(a);//列印 } }

結果為3,這裡就有問題了,我命名讓他指向第一個節點,應該是1才對呀,怎麼會變成第三個呢?debug的結果是這樣的:這裡寫圖片描述

可以看出來,這裡的head直接指向的是3,剛好反過來了,所以剛才得出的值是3。

看似很簡單的問題,我還是花了很長時間才發現問題。其實原因是這樣新增節點時,current所指向的節點並沒有變,還是在頭結點位置,新增節點並不能使current表示的節點後移,所以解決辦法是在每次添加了新的節點後把current往後移一下,讓它指向新新增的節點,這樣才能在新新增的節點後面再新增節點。程式碼如下:

public class main_test1 {

    public static void main(String[] args) {
        test1 head;
        test1 current;
        current=head=new test1(null);//這裡也表示current指向頭結點
        current.setnext(new test1(1,head.next));
        current=current.next;//使current指向下一個節點
        current.setnext(new test1(2,current.next));
        current=current.next;
        current.setnext(new test1(3,current.next));
        current=current.next;

        current=head.next;

        int a=(int)current.getelement();
        System.out.println(a);
    }

}

結果為1。這次正確了,再看debug圖:
這裡寫圖片描述
看,這下順序就對了。
這裡主要的問題是,沒有想到新增新節點後想在其後面繼續新增,是要先移動當前current所指向的節點的位置的。感覺以後這個思路會給我幫助,記錄下來方便以後複習。

對這篇部落格的一些地方做一些補充,記錄自己思考的結果:
第八點:連結串列有環,如何判斷相交:
我自己想了另一種方法,應該比部落格中的效率高一點,其實也是借鑑了上面的思想,設定三個節點,其中一快一慢(和前面的一個意思,快的前進兩格)指向head1,另一個快指向head2。這裡思路是:如果兩個有環連結串列相交(這裡不考慮兩個無環連結串列相交的情況),那麼當前面設定的三個節點都進入環中的時候,就可以利用head2_fast去追趕head1_low,這裡最關鍵的地方是考慮什麼時候停止追趕,因為環內是可以無限迴圈的。仔細琢磨第5點的原理就能找到關鍵點了,看程式碼理解吧:

    public boolean isIntersect(Node head1,Node head2){
        //設定三個節點
        Node head1_low=head1;
        Node head1_fast=head1;
        Node head2_fast=head2;

        while(head1_fast!=null && head1_fast.next!=null && head2_fast!=null && head2_fast.next!=null){//如果有無環連結串列直接判斷不相交
            head1_low=head1_low.next;
            head1_fast=head1_fast.next.next;
            head2_fast=head2_fast.next.next;
            if(head1_low==head2_fast)//過程中如果運氣好,可以直接得到相交
                return true;
            else if(head1_low==head1_fast){//核心,也就是找到慢指標和快指標相交的點後就進行head2_fast追趕head1_low
                do{//這裡有個問題,如果head2除了環之外的部分特別長,那麼這裡是不成立的,就需要設立第四個節點,後面給出
                    head1_low=head1_low.next;
                    head2_fast=head2_fast.next.next;
                    if(head1_low==head2_fast)
                        return true;
                }while(head1_low.next!=head1_fast);//如果相交,head1_low跑一圈內必然能夠相等。
                return false;
            }

        }
        return false;
    }

給出上面的修正程式碼,其實就是要確認開始追趕時head2_fast已經進入環內,不然會出現head1_low跑完一圈head2_fast還未進環的情況,同樣通過給head2_fast也找個相交點來判斷是否進環:

        public boolean isIntersect(Node head1,Node head2){
            Node head1_low=head1;
            Node head1_fast=head1;
            Node head2_low=head2;
            Node head2_fast=head2;

            while(head1_fast!=null && head1_fast.next!=null && head2_fast!=null && head2_fast.next!=null){
                head1_low=head1_low.next;
                head1_fast=head1_fast.next.next;
                head2_low=head1_low.next;
                head2_fast=head2_fast.next.next;
                if(head1_low==head2_fast)
                    return true;
                else if(head1_low==head1_fast){
                    while(head2_low!=head2_fast){
                        head2_low=head1_low.next;
                        head2_fast=head2_fast.next.next;
                        if(head2_fast!=null && head2_fast.next!=null)
                            return false;
                    }
                    do{
                        head1_low=head1_low.next;
                        head2_fast=head2_fast.next.next;
                        if(head1_low==head2_fast)
                            return true;
                    }while(head1_low.next!=head1_fast);
                    return false;
                }
                else if(head2_low==head2_fast){
                    while(head1_low!=head1_fast){
                        head1_low=head1_low.next;
                        head1_fast=head1_fast.next.next;
                        if(head1_fast!=null && head1_fast.next!=null)
                            return false;
                    }
                    do{
                        head1_low=head1_low.next;
                        head2_fast=head2_fast.next.next;
                        if(head1_low==head2_fast)
                            return true;
                    }while(head1_low.next!=head1_fast);
                    return false;
                }

            }
            return false;
        }

其實變化不大,看一看就明白,不過這樣一來和原方法比較優勢就不明顯了。總之提供一種思路吧(以上方法沒有經過檢驗,可能有瑕疵)。

第九點:兩連結串列相交的第一個公共節點:
博主沒有寫這種方法,也許是他覺得沒必要,因為所有東西部落格上都提到了,有心人應該是自己能推理出來的:
把一個連結串列接到另一個連結串列的尾部,形成環,再用判斷環的入口,就ok了。是不是所有東西部落格裡都有寫到?

相關推薦

java資料結構單鏈實現原理

再次學習資料額結構,看到前面的單鏈表,感覺裡面的思路很不錯,自己動手寫程式碼嘗試一下,果然一動手就發現自己並沒有完全理解。這裡主要記錄我花了很長時間才理解的地方,不去考慮增刪改查,我覺得這些功能在很多地方都實現過,不是重點,也有很多資料可查。 單鏈表的原理網上

資料結構——單鏈實現

鏈式儲存特點 在鏈式儲存中,節點之間的儲存單元地址可能是不連續的。鏈式儲存中每個結點都包含兩部分:儲存元素本身的資料域和儲存結點地址的指標域。結點中的指標指向的是下一個結點,也就是儲存的下一個結點的地址。 鏈式儲存的實現 1.建立連結串列 在建立連結串列時,頭結點不儲存資料,

資料結構——單鏈實現及操作(c語言)

#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #d

資料結構 單鏈實現 純程式碼

單鏈表操作函式原型宣告 node_t *list_init(); //顯示單鏈表 void display(node_t *head); //在單鏈表上查詢第i個節點的存放地址 node_t *find(node_t *head,int i); //在單鏈表上第I個節點後面

C/C++,資料結構單鏈實現約瑟夫環

約瑟夫環——圍成一圈,定義一個數值K,從任意位置開始計數,每走K步刪除當前位置結點,直到剩下最後一個結點,求最後一個結點//單鏈表結構以及Find函式參見 2016-1-2 13:56 發表部落格SLi

java資料結構之手動實現單鏈

package com.example.demo; // 1、定義要儲存物件的類: class Phone {// 此類提供要儲存的資料 private String brand; private double price; public Phon

資料結構(Java):用單鏈實現多項式相加

要求: 1.已知有兩個多項式Pn(x)和Qm(x),並且在Pn(x)和Qm(x)中指數相差很多,設計演算法,求Pn(x)+Qm(x) 2.進行加法運算時不重新開闢儲存空間。 //定義節點類 class Node{ public int coef;//係數 p

資料結構-單鏈進階之快慢指標原理(快速查詢法)

面試題:快速找到未知長度單鏈表的中間節點?這個問題的解決方法分為普通方法和高階方法。1.普通方法即我們大家都能一下子想到的,首先遍歷一遍獲取總長度L,然後再次遍歷迴圈至L/2即可;時間複雜度為:O(L+L/2)=O(3/2L)程式碼簡單實現:typedef struct {

資料結構單鏈的定義(Java

定義一個介面 public interface ILinarList<E> { public abstract boolean add(E item); //新增元素 public abstract boole

資料結構-單鏈操作

// // main.c // Link_List // // Created by Smallflyfly on 2018/11/9. // Copyright © 2018 fang. All rights reserved. // #include <stdio.h>

python與資料結構-單鏈

https://www.bilibili.com/video/av21540971/?p=10 1、python 中變數標識的本質 python 中等號的本質就是一個"引用連結”(變數皆指標),【與c和c++不一樣,c、c++是&表示地址,指標】 2、 3、遍歷連結串列

資料結構-單鏈

說明     與順序表相比,允許儲存空間不連續,插入刪除時不需要移動大量的元素,只需修改指標即可,但查詢某個元素,只能從頭遍歷整個連結串列。 程式碼 /* ** slink create by yubo.wang 2018.9.12 */ #include <st

資料結構——單鏈(環)

一、環 標題   二、建立環 //建立環 public void createLoop(){ Entry cur = this.head; while(cur.next != null){

嚴蔚敏版資料結構——單鏈

嚴蔚敏版資料結構——單鏈表的操作       記得前上個禮拜,我寫過的一個版本的單鏈表的建立。今天寫下了這個嚴蔚敏版的單鏈表。梳理了一下思路,其基本演算法還是一樣的,還是那句話,理解,理解,理解最重要。這個版本的單鏈表我要提醒自己的是:1、這是直接在函式中採用引用L

資料結構--順序實現資料處理系統(C語言)

#include<stdio.h> #include<stdlib.h> #define MAXSIZE 10 #define OK 1 #define ERROR 0 #define true 1 typedef int Status;

資料結構-單鏈交換節點

普通情況的結點交換 temp_pre->next = p; p_pre->next = p->next;//key step p->next = temp->next; temp->

資料結構--單鏈

single_linklist.h #ifndef __SINGLE_LINKLIST_H__ #define __SINGLE_LINKLIST_H__ #include <stdio.h> #include <stdlib.h>

資料結構-單鏈翻轉

public class Node {     private Node next;     private int value;          public boolean hasNext() {         return next != null;     }

浙大資料結構 單鏈逆轉

6-8 單鏈表逆轉 (20 分) 本題要求實現一個函式,將給定的單鏈表逆轉。 函式介面定義: List Reverse( List L ); 其中List結構定義如下: typedef struct Node *PtrToNode; struct Node {

C語言資料結構單鏈之溫故而知新

拋棄繁雜的定義,以實用,實戰的角度來學習資料結構,這將使得資料結構的學習非常的簡單。前面已經學習了單鏈表的建立操作:http://blog.csdn.net/morixinguan/article/details/68951912這節,將單鏈表溫習的筆記共享出來,然後寫一個例