1. 程式人生 > 實用技巧 >關於C語言實現單鏈表中的指標問題

關於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 獲取具體某個元素的結點(這個看情況,如果只是找到連結串列中第幾個元素的值,那麼就沒必要用二級指標)