單鏈表帶頭結點&不帶頭結點


轉自:http://blog.csdn.net/xlf13872135090/article/details/8857632

 

Node *head;  //聲明頭結點
 
帶頭結點初始化

void InitList(Node **head){

     *head=(Node *)malloc( sizeof(Node));
     (*head)->next=NULL;
}
 
帶頭結點尾插入,統一操作
方式一:
void CreatList(Node **head){
     Node *r=*head,*s;
     int a;
     while(scanf("%d",&a)){
          if(a!=0){
               s=(Node *)malloc(sizeof(Node));
               s->value=a;
               r->next=s;
               r=s;    
          }
          else{    
               r->next=NULL;
               break;    
          }
     }
}
調用CreatList(&head);
 
方式二:
void CreatList(Node *head){
     Node *r=head,*s;
     ... //下面的都一樣
}
調用CreatList(head);
 
------------------------------------------------------------------------------------------------------
 
不帶頭結點初始化
方式一:
void InitList(Node **head){
     *head=NULL;
}
調用InitList(&head);
 
方式二:
void InitList(Node *head){
     head=NULL;
}
調用InitList(head);
 
不帶頭結點尾插入,第一個節點與其他節點分開操作
void CreatList(Node  **head){
     Node *p,*t;         /*p工作指針,t臨時指針*/
     int a,i=1;
     while(scanf("%d",&a)){
          if(a!=0){
               t=(Node *)malloc(sizeof(Node));
               t->value=a;
               if(i==1){
                    *head=t;    
               }
               else{
                    p->next=t;
               }
               p=t;
          }
          else{    
               p->next=NULL;
               break;    
          }
          i++;
     }
}
調用CreatList(&head);
 
 
一、兩者區別:
     1、不帶頭結點的單鏈表對於第一個節點的操作與其他節點不一樣,需要特殊處理,這增加了程序的復雜性和出現bug的機會,因此,通常
          在單鏈表的開始結點之前附設一個頭結點。
     2、帶頭結點的單鏈表,初始時一定返回的是指向頭結點的地址,所以一定要用二維指針,否則將導致內存訪問失敗或異常。
     3、帶頭結點與不帶頭結點初始化、插入、刪除、輸出操作都不樣,在遍歷輸出鏈表數據時,帶頭結點的判斷條件是while(head->next!=NULL),
          而不帶頭結點是while(head!=NULL),雖然頭指針可以在初始時設定,但是如1所述,對於特殊情況如只有一個節點會出現問題。
         
 
二、為什么不帶頭結點初始化有2種方式,而帶頭結點只有1種方式呢?
 
     因為不帶頭結點聲明Node *head 時;C編譯器將其自動初始化為NULL,於是根本不需要調用InitList(head);也即不帶頭結點的初始化
是個偽操作。而帶頭結點的初始化在堆開辟了一段內存,需要修改head指針變量指向的地址(即head的值),所以要修改head的值,必須傳保
存head變量的地址(即二維指針)。而直接調用CreatList(head);相當於傳head變量的值,函數修改的是head的副本,無法真正改變head的值。 
 
     注:這里可以將head指針看成一個變量(不管它保存的是地址),就比較好理解了。
      
 
三(key)、其實本質上還是傳值,傳址的問題,只不過指針本身保存的地址,讓這個過程變得有點糾結。在函數調用需要修改指針變量的指向(value)時,
 應該傳遞指針變量的地址(address)。
      另外,對於函數的形參是指針時,只要該參數不在左邊(即都是右值操作),二維指針(形參)就可以簡化為一維指針。如上面帶頭結點的尾插
簡化版本。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM