乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      單向鏈表(單鏈表)的Java實(shí)現(xiàn)

       T_Per_Lib 2014-04-23

        最近被問到鏈表,是一個(gè)朋友和我討論Java的時(shí)候說的。說實(shí)話,我學(xué)習(xí)編程的近一年時(shí)間里,學(xué)到的東西還是挺少的。語言是學(xué)了Java和C#,關(guān)于Web的學(xué)了一點(diǎn)Html+css+javascript。因?yàn)楸容^偏好,學(xué)習(xí)WinForm時(shí)比較認(rèn)真,數(shù)據(jù)庫操作也自己有所研究。但鏈表這個(gè)東西我還真沒有學(xué)習(xí)和研究過,加上最近自己在看WPF,而課程也到了JSP了,比較緊。

        但是我還是抽了一個(gè)晚上加半天的時(shí)間看了一下單向鏈表。并且使用Java試著寫了一個(gè)實(shí)例出來。沒有接觸過鏈表的朋友可以作為參考,希望大家多提寶貴意見。

        當(dāng)然,我們首先解釋一下什么是鏈表。就我所知,鏈表是一種數(shù)據(jù)結(jié)構(gòu),和數(shù)組同級(jí)。比如,Java中我們使用的ArrayList,其實(shí)現(xiàn)原理是數(shù)組。而LinkedList的實(shí)現(xiàn)原理就是鏈表了。我的老師說,鏈表在進(jìn)行循環(huán)遍歷時(shí)效率不高,但是插入和刪除時(shí)優(yōu)勢明顯。那么他有著愈十年的編程經(jīng)驗(yàn),我是相信的。不過不知道他是否是說雙向鏈表,我們?cè)诖四刂粚?duì)單向鏈表做一個(gè)了解。

        鏈表(Chain本文所說鏈表均為單向鏈表,以下均簡稱單向鏈表)實(shí)際上是由節(jié)點(diǎn)(Node)組成的,一個(gè)鏈表擁有不定數(shù)量的節(jié)點(diǎn)。而向外暴露的只有一個(gè)頭節(jié)點(diǎn)(Head),我們對(duì)鏈表的所有操作,都是直接或者間接地通過其頭節(jié)點(diǎn)來進(jìn)行的。

        節(jié)點(diǎn)(Node)是由一個(gè)需要儲(chǔ)存的對(duì)象及對(duì)下一個(gè)節(jié)點(diǎn)的引用組成的。也就是說,節(jié)點(diǎn)擁有兩個(gè)成員:儲(chǔ)存的對(duì)象、對(duì)下一個(gè)節(jié)點(diǎn)的引用。

        這樣說可能大家不是很明白,我貼一張圖大家可能更容易理解。

        

        那么大家可能清除了,為什么說有了頭節(jié)點(diǎn)就可以操作所有節(jié)點(diǎn)。因?yàn)橛兄粩嗟囊寐铮?/p>

        那么在鏈表里的屬性大概就只有兩個(gè)了:頭節(jié)點(diǎn)和節(jié)點(diǎn)數(shù)量。當(dāng)然,根據(jù)需要,我們通常需要更多的屬性。

        簡單的鏈表可以寫為下面的樣子:

      復(fù)制代碼
       1 package myChain;
       2 
       3 /**
       4  * (單向)鏈表
       5  * 
       6  * @author Johness
       7  */
       8 public class PersonChain {
       9     private PersonChainNode head; // 頭節(jié)點(diǎn)
      10     private int size; // 鏈表的實(shí)體(即節(jié)點(diǎn)的數(shù)量)
      11     private int modCount; // 鏈表被操作的次數(shù)(備用)
      12 
      13     /**
      14      * 獲得鏈表中節(jié)點(diǎn)數(shù)量
      15      * 
      16      * @return 鏈表中節(jié)點(diǎn)數(shù)
      17      */
      18     public int getSize() {
      19         return this.size;
      20     }
      21 
      22     /**
      23      * 添加節(jié)點(diǎn)的一般方法
      24      * 
      25      * @param p
      26      *            添加到鏈表節(jié)點(diǎn)的對(duì)象 由于實(shí)現(xiàn)細(xì)節(jié),作為唯一標(biāo)識(shí),同一個(gè)編號(hào)的Person只能添加一次
      27      */
      28     public void addNode(Person p) {
      29         if (!contains(p.personNo)) { // 如果鏈表中沒有該對(duì)象,則準(zhǔn)備添加
      30             if (head != null) { // 如果有頭節(jié)點(diǎn),則添加新節(jié)點(diǎn)作為頭節(jié)點(diǎn)
      31                 head = new PersonChainNode((myChain.Person) p, head);
      32                 size++;
      33                 modCount++;
      34             } else { // 如果沒有頭節(jié)點(diǎn),則添加對(duì)象作為頭節(jié)點(diǎn)
      35                 head = new PersonChainNode((myChain.Person) p, null);
      36                 size++;
      37                 modCount++;
      38             }
      39         }
      40     }
      41 }
      復(fù)制代碼

        以上的代碼就是一般鏈表的骨架了。擁有兩個(gè)重要屬性。

        那么做為能添加到鏈表的節(jié)點(diǎn)又該長什么樣子呢?

        我們可以寫作如下:

      復(fù)制代碼
       1 package myChain;
       2 
       3 /**
       4  * (節(jié)點(diǎn))實(shí)體,封裝了'人'這個(gè)對(duì)象和下一個(gè)實(shí)體的引用
       5  * 該實(shí)體將作為(單向)鏈表的節(jié)點(diǎn)
       6  * @author Johness
       7  */
       8 public class PersonChainNode {
       9     Person person;                            //
      10     PersonChainNode nextNode;        // 該對(duì)象('人')保存的下一個(gè)對(duì)象的引用
      11     
      12     // 獲取當(dāng)前實(shí)體對(duì)象('人')
      13     public Person getPerson(){
      14         return this.person;
      15     }
      16     
      17     // 獲取下一個(gè)實(shí)體
      18     public PersonChainNode getNextNode(){
      19         return this.nextNode;
      20     }
      21     
      22     // 構(gòu)造方法
      23     public PersonChainNode (Person p,PersonChainNode ep){
      24         this.person = p;
      25         this.nextNode = ep;
      26     }
      27 }
      復(fù)制代碼

        當(dāng)然了,這只是個(gè)大概的樣子。

        那么我最后在把層次梳理一下:鏈表是由不定數(shù)量的節(jié)點(diǎn)連接(通過相互之間的引用)起來的,由于這種關(guān)系,在鏈表里我們只定義了頭節(jié)點(diǎn)和節(jié)點(diǎn)數(shù)量。節(jié)點(diǎn)是由存儲(chǔ)的對(duì)象及對(duì)下一個(gè)“節(jié)點(diǎn)”的引用封裝而成。

        在添加節(jié)點(diǎn)到鏈表中時(shí),首先添加的節(jié)點(diǎn)后置后,新添加的節(jié)點(diǎn)作為頭節(jié)點(diǎn)引用前一個(gè)添加的節(jié)點(diǎn)。

        廢話不多說,貼上我的例子,老師說我廢話多……

       ?。ㄒ韵碌睦虞^為簡陋,大家不要笑話我哈)

      復(fù)制代碼
       1 package myChain;
       2 
       3 /**
       4  * '人' 類
       5  * @author Johness
       6  * @version 1.0
       7  */
       8 public class Person {
       9     String name;        // 姓名
      10     int age;                // 年齡
      11     int personNo;     // 編號(hào),用作唯一標(biāo)識(shí)
      12     
      13     // 帶參構(gòu)造方法
      14     public Person(String name, int age, int personNo) {
      15         this.name = name;
      16         this.age = age;
      17         this.personNo = personNo;
      18     }
      19 
      20     // 獲取姓名
      21     public String getName(){
      22         return this.name;
      23     }
      24     
      25     // 獲取年齡
      26     public int getAge(){
      27         return this.age;
      28     }
      29     
      30     // 獲取編號(hào)
      31     public int getPersonNo(){
      32         return this.personNo;
      33     }
      34     
      35     // 用于輸出的信息
      36     public String toString(){
      37         return "姓名:" + this.name + "\t年齡:" + this.age +"\t編號(hào)" + this.personNo;
      38     }
      39 }
      復(fù)制代碼

        

      復(fù)制代碼
       1 package myChain;
       2 
       3 /**
       4  * (節(jié)點(diǎn))實(shí)體,封裝了'人'這個(gè)對(duì)象和下一個(gè)實(shí)體的引用
       5  * 該實(shí)體將作為(單向)鏈表的節(jié)點(diǎn)
       6  * @author Johness
       7  */
       8 public class PersonChainNode {
       9     Person person;                            //
      10     PersonChainNode nextNode;        // 該對(duì)象('人')保存的下一個(gè)對(duì)象的引用
      11     
      12     // 獲取當(dāng)前實(shí)體對(duì)象('人')
      13     public Person getPerson(){
      14         return this.person;
      15     }
      16     
      17     // 獲取下一個(gè)實(shí)體
      18     public PersonChainNode getNextEntity(){
      19         return this.nextNode;
      20     }
      21     
      22     // 構(gòu)造方法
      23     public PersonChainNode (Person p,PersonChainNode ep){
      24         this.person = p;
      25         this.nextNode = ep;
      26     }
      27     
      28     // 構(gòu)造方法
      29     public PersonChainNode (Person p){
      30         this.person = p;
      31     }
      32 }
      復(fù)制代碼
      復(fù)制代碼
        1 package myChain;
        2 
        3 /**
        4  * (單向)鏈表
        5  * 
        6  * @author Johness
        7  */
        8 public class PersonChain {
        9     private PersonChainNode head; // 頭節(jié)點(diǎn)
       10     private int size; // 鏈表的實(shí)體(即節(jié)點(diǎn)的數(shù)量)
       11     private int modCount; // 鏈表被操作的次數(shù)(備用)
       12 
       13     /**
       14      * 獲得鏈表中節(jié)點(diǎn)數(shù)量
       15      * 
       16      * @return 鏈表中節(jié)點(diǎn)數(shù)
       17      */
       18     public int getSize() {
       19         return this.size;
       20     }
       21 
       22     /**
       23      * 添加節(jié)點(diǎn)的一般方法
       24      * 
       25      * @param p
       26      *            添加到鏈表節(jié)點(diǎn)的對(duì)象 由于實(shí)現(xiàn)細(xì)節(jié),作為唯一標(biāo)識(shí),同一個(gè)編號(hào)的Person只能添加一次
       27      */
       28     public void addNode(Person p) {
       29         if (!contains(p.personNo)) { // 如果鏈表中沒有該對(duì)象,則準(zhǔn)備添加
       30             if (head != null) { // 如果有頭節(jié)點(diǎn),則添加新節(jié)點(diǎn)作為頭節(jié)點(diǎn)
       31                 head = new PersonChainNode((myChain.Person) p, head);
       32                 size++;
       33                 modCount++;
       34             } else { // 如果沒有頭節(jié)點(diǎn),則添加對(duì)象作為頭節(jié)點(diǎn)
       35                 head = new PersonChainNode((myChain.Person) p, null);
       36                 size++;
       37                 modCount++;
       38             }
       39         }
       40     }
       41 
       42     /**
       43      * 通過編號(hào)刪除對(duì)象
       44      * 
       45      * @param personNo
       46      *            要?jiǎng)h除對(duì)象的編號(hào)
       47      */
       48     public void deleteNode(int personNo) {
       49         if (size == 0) { // 如果當(dāng)前鏈表節(jié)點(diǎn)數(shù)為零
       50             return;
       51         }
       52         if (size == 1) { 
       53             // 如果只有一個(gè)節(jié)點(diǎn)并且正是需要?jiǎng)h除的對(duì)象
       54             if (head.person.personNo == personNo) {
       55                 head = null;
       56                 size = 0;
       57             }
       58             return;
       59         }
       60         // 如果不存在該對(duì)象編號(hào)
       61         if (!contains(personNo)) {
       62             return;
       63         }
       64 
       65         // 較為復(fù)雜的刪除,定義整型保存被刪除的節(jié)點(diǎn)的索引
       66         //(刪除和索引都是不存在的,這里只是一個(gè)說法)
       67         int index = 0;
       68         // 循環(huán)遍歷,找到刪除節(jié)點(diǎn)的索引
       69         for (PersonChainNode p = head; p != null; p = p.nextNode) {
       70             if (!(p.person.personNo == personNo)) {
       71                 index++;
       72             } else {
       73                 break;
       74             }
       75         }
       76         // 如果刪除的是第一個(gè)節(jié)點(diǎn)(即頭節(jié)點(diǎn))
       77         if (index == 0) {
       78             head = new PersonChainNode(head.nextNode.person,
       79                     head.nextNode.nextNode);    // 設(shè)置頭節(jié)點(diǎn)后一個(gè)節(jié)點(diǎn)為新的頭節(jié)點(diǎn)
       80             size--;                                            // 鏈表節(jié)點(diǎn)數(shù)減一
       81             modCount++;                                // 鏈表被操作次數(shù)加一
       82             return;
       83         }
       84         
       85         // 如果刪除的節(jié)點(diǎn)不是第一個(gè)節(jié)點(diǎn)
       86         // 循環(huán)遍歷,找到被刪除節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)
       87         // 其索引下標(biāo)用count保存
       88         int count = 0;
       89         for (PersonChainNode p = head; p != null; p = p.nextNode) {
       90             if (count == index - 1) {    // 如果找到了被刪除節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)
       91                 if (index == size - 1) {    // 如果被刪除節(jié)點(diǎn)是最后一個(gè)節(jié)點(diǎn)
       92                     p.nextNode = null;    // 將被刪除節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)的引用指向空引用
       93                 } else {                            // 如果被刪除節(jié)點(diǎn)不是最后一個(gè)節(jié)點(diǎn)
       94                     p.nextNode = p.nextNode.nextNode;    // 將被刪除節(jié)點(diǎn)前一個(gè)節(jié)點(diǎn)對(duì)其引用指向被刪除節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)
       95                 }
       96                 size--;                // 減一數(shù)量
       97                 modCount++;    // 加一操作次數(shù)
       98                 return;
       99             }
      100             count++;                // 沒有找到,索引加一
      101         }
      102     }
      103 
      104     /**
      105      * 通過姓名查找對(duì)象
      106      * 未實(shí)現(xiàn)
      107      * @param name
      108      *            對(duì)象姓名
      109      * @return 對(duì)象數(shù)組,可能多個(gè)
      110      */
      111     public Person[] searchNodeByPersonName(String name) {
      112         return null;
      113     }
      114 
      115     /**
      116      * 通過年齡查找對(duì)象
      117      * 未實(shí)現(xiàn)
      118      * @param age
      119      *            對(duì)象年齡
      120      * @return 對(duì)象數(shù)組,可能多個(gè)
      121      */
      122     public Person[] searchPersonByAge(int age) {
      123         return null;
      124     }
      125 
      126     /**
      127      * 通過編號(hào)查找對(duì)象
      128      * 由于編號(hào)是唯一標(biāo)識(shí),循環(huán)遍歷查找并返回即可
      129      * @param personNo
      130      *            對(duì)象編號(hào)
      131      * @return 查找到的對(duì)象或者null
      132      */
      133     public Person searchNode(int personNo) {
      134         Person p = null;
      135         for (PersonChainNode pcn = head; pcn != null; pcn = pcn.nextNode) {
      136             if (pcn.person.personNo == personNo) {
      137                 p = pcn.person;
      138             }
      139         }
      140         return p;
      141     }
      142 
      143     /**
      144      * 通過原對(duì)象修改及傳入值修改該對(duì)象屬性
      145      * 
      146      * @param personNo
      147      *            要修改的對(duì)象編號(hào)
      148      * @param value
      149      *            通過傳入值的類型判斷修改 只能修改姓名或年齡
      150      */
      151     public void editNode(int personNo, Object value) {
      152         // 通過作為唯一標(biāo)識(shí)的編號(hào)查找到對(duì)象
      153         Person target = searchNode(personNo);
      154         if (target == null) {    // 如果對(duì)象為null
      155             return;
      156         }
      157         if (value == null) {    // 如果傳入?yún)?shù)為null
      158             return;
      159         }
      160         // 如果傳入?yún)?shù)為字符串類型
      161         if (value.getClass() == java.lang.String.class) {
      162             target.name = value.toString();
      163             return;
      164         }
      165         try {
      166             // 如果傳入?yún)?shù)為整型
      167             target.age = Integer.parseInt(value.toString());
      168             return;
      169         } catch (Exception ex) {
      170             // 如果傳入?yún)?shù)類型錯(cuò)誤
      171             return;
      172         }
      173     }
      174 
      175     /**
      176      * 通過對(duì)象編號(hào)打印對(duì)象
      177      * 
      178      * @param personNo
      179      *            對(duì)象編號(hào)
      180      */
      181     public void printNode(int personNo) {
      182         Person target = searchNode(personNo);
      183         if (target == null) {
      184             return;
      185         }
      186         System.out.println(target.toString());
      187     }
      188 
      189     /**
      190      * 判斷指定對(duì)象是否存在鏈表中
      191      * 
      192      * @param personNo
      193      *            對(duì)象編號(hào)
      194      * @return true表示存在該對(duì)象,false表示不存在該對(duì)象
      195      */
      196     public boolean contains(int personNo) {
      197         if (size != 0) {
      198             for (PersonChainNode pcn = head; pcn != null; pcn = pcn.nextNode) {
      199                 if (pcn.person.personNo == personNo) {
      200                     return true;
      201                 }
      202             }
      203         }
      204         return false;
      205     }
      206 
      207     // 排序方法
      208 
      209     /**
      210      * 通過姓名排序
      211      */
      212     public void sortByPersonName() {
      213     }
      214 
      215     /**
      216      * 通過年齡排序
      217      */
      218     public void sortByPersonAge() {
      219     }
      220 
      221     /**
      222      * 默認(rèn)排序,通過編號(hào)排序 
      223      * 使用冒泡排序,增加了判斷以提高效率
      224      */
      225     public void sort() {
      226         boolean jx = true;        // 冒泡排序的簡化方法
      227         for (PersonChainNode pcn = head; pcn != null && jx; pcn = pcn.nextNode) {
      228             jx = false;
      229             for (PersonChainNode pc = head; pc != null && pc.nextNode != null; pc = pc.nextNode) {
      230                 if (pc.person.personNo > pc.nextNode.person.personNo) {
      231                     Person temp = pc.person;
      232                     pc.person = pc.nextNode.person;
      233                     pc.nextNode.person = temp;
      234                     jx = true;
      235                 }
      236             }
      237         }
      238     }
      239 
      240     /**
      241      * 打印整個(gè)鏈表
      242      */
      243     public void printAll() {
      244         if (size != 0) {
      245             for (PersonChainNode pcn = head; pcn != null; pcn = pcn.nextNode) {
      246                 System.out.println(pcn.person.toString());
      247             }
      248         }
      249     }
      250 }
      復(fù)制代碼

        2012-04-11 21:33:32

        那么實(shí)際上呢,我們?cè)贘ava編程中使用的LinkedList就是在其內(nèi)部維護(hù)著一個(gè)鏈表。

        實(shí)際上的操作不外乎增刪改查,不同的是由于高度封裝,Jdk的LinkedList是使用索引來取得對(duì)象并進(jìn)行操作的。

        和以上我的例子是不盡相同的,因?yàn)槲沂前踩凑兆约旱男枨髞碜龅?,這樣比較簡單,實(shí)際上為了代碼重用復(fù)用和擴(kuò)展。Jdk內(nèi)的鏈表節(jié)點(diǎn)不知道保存的信息,因此沒有辦法以除了索引之外的方式獲取元素。

        

        今天課程到了Java集合框架,老師略微提了一下單向不循環(huán)鏈表。

        我將老師的舉例改編一下,幫助大家理解:

        老師需要找某一個(gè)同學(xué),但是碰巧實(shí)在放假的時(shí)間內(nèi)。同學(xué)們所處的位置都不一樣。老師知道班長的手機(jī)號(hào)碼,所以老師打電話給了班長,班長說他也不知道,但是他知道'我'的電話,他又打給我,我也不知道那位同學(xué)的地址,我又繼續(xù)向下一個(gè)同學(xué)打電話,直到找到他。

        那么在以上示例中,加入每一個(gè)同學(xué)都有另一個(gè)同學(xué)的電話(有且僅有一個(gè))。

        我們就可以說符合單向鏈表的環(huán)境了。大家可以理解記憶。

       

        大家都知道,我們所創(chuàng)建的對(duì)象是保存在內(nèi)存中的。數(shù)組是如此,鏈表也是如此。

        但是數(shù)組是一個(gè)整體空間,所有元素共用。就比如教室內(nèi)上課的同學(xué)們。教室的容量是固定的,同學(xué)可少不可多,老師若希望進(jìn)行查詢,能夠一眼看出來。

        鏈表和其節(jié)點(diǎn)是不同的存儲(chǔ)位置,比如我們一個(gè)班畢業(yè)了。有的同學(xué)去了國外,有的去了北京。大家的位置不同,但是有一定聯(lián)系的。

       

        2012-04-23 19:16:20

        

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多