關於C語言實現單鏈表中的指針問題


導言

筆者最近學習嚴薇敏教授的《數據結構》,同時也參考B站上王道考研的數據結構視頻,發現單鏈表傳入函數參數這一方面教材與視頻,與網絡上的一些實現寫法各有不同,有點迷惑。經過查了一些資料以后,終於撥雲見日。寫下這篇文章,希望為后來的同學們有所幫助。水平不足,還請多多指正!

指針

指針是指向內存中一定大小內存區域的變量。定義一個指針如:

int *p;
 

但這樣只是聲明了一個指針變量p,p指向哪里我們不清楚,需要指定這個指針變量指向的內存區域

int x = 2;
int *p = NULL; //初始化,避免p是野指針
p = &x;        //讓p指向x

 

指針變量實際上存放的是目標區域的內存地址。

我們要注意區分*p = 和 p =這兩種情況

*p = 2;       //讓p指向的內存區域中的值變成2
p = &a;       //讓指針p指向內存中的區域a,也就是讓p的值為a的地址

 

注意:指針變量的值是地址,取內容符號與指針變量搭配,改變的不是指針的值,而是指針指向的內存區域的值

函數中參數傳遞問題

C語言中,參數傳遞有兩種,一個是值傳遞,一個是地址傳遞。值傳遞情況下,C程序只是獲得了值,也就是變量的拷貝,在C程序內對變量的任何操作都不會引起內存中原本的變量的變化。想要改變傳遞進來的參數,就需要進行地址傳遞。

void test(int *a){
    *a = 2; 
}
int main(){
    int x = 0;
    test(&a);         //傳入變量的地址
    printf("%d\n",x); //輸出結果為2
    return 0;
}
 

鏈表中指針的使用(帶頭結點為例)

我們在單鏈表中,用到了指針來實現單鏈表

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode, *LinkList;
​
LinkList L;
 

怎么理解這個L?

我們要知道,LinkList本質上是一個指針,它指向的是內存中大小為的LNode類型區域。那么,L這個指針,存儲的應該是目標區域的地址。

一開始我們只是聲明了這么一個指針L,還沒有將它指向一片內存區域。為了將它指向一片內存區域,我們需要使用malloc函數來分配內存空間

L = (LNode *)malloc(sizeof(LNode));  //注意要用(LNode *)或者(LinkList)
//來對malloc函數返回的地址進行類型轉換
if (L == NULL) return false;

 

這個時候我們就要注意,這個對單鏈表進行初始化的函數initList,接收的參數應該是怎么樣的?

經過驗證,我們得知,如果直接傳入指針L,那么我們將不能更改內存中L的指向區域。為了改變指針L,我們有兩種方案可以選擇:

  1. 通過return語句來返回地址

    LinkList initList(LinkList L){
        L = (LinkList)malloc(sizeof(LNode));
        if (L == NULL) return NULL;
        else{
            L->next = NULL; //設置L指向的區域(頭結點)的next域的值
            return L;
        }
    }
    ​
    int main(){
        LinkList L;
        L = initList(L);
        return 0;
    }
     
  2. 使用二級指針,來對一級指針L的值(指向的內存區域是哪一片)進行改變。

    int initList(LinkList *L){ //此處的L是二級指針,指向的是:指向頭結點的頭指針
        *L = (LinkList)malloc(sizeof(LNode));  
    //*L就是二級指針的內容,也就是一級指針存儲的值,也就是目標區域地址。所以,可以直接把*L當頭指針用 if (*L == NULL) return 0; else{ (*L)->next = NULL; return 1; } } ​ int main(){ LinkList L; initList(&L); return 0; }
     

必須使用二級指針的操作

根據單鏈表的基本操作,我們總結一下必須要用二級指針的情況,實際上也就是對單鏈表內容進行更改的情況:

  • initList 鏈表初始化

  • listInsert 向指定位置插入

  • listDelete 刪除指定位置元素

  • destoryList 鏈表銷毀

  • getElem 獲取具體某個元素的結點(這個看情況,如果只是找到鏈表中第幾個元素的值,那么就沒必要用二級指針)




免責聲明!

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



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