關於連結串列中結構體typedef相關疑惑的解釋
本文將以單鏈表和靜態連結串列的初始化程式碼(c++)為例,具體分析了結構體中typedef struct LNode{....} LNode, *LinkList, SLinkList[MaxSize];
的相關問題,並補充了C++中引用型別的一點知識。
第一部分
首先給出單鏈表的初始化程式碼:
typedef struct LNode { ElemType data; struct LNode *next; } LNode, *LinkList; bool InitList(LinkList &L) { L = (LNode *) malloc(sizeof(LNode)); if (L == NULL) { return false; } L -> next = NULL; return true; } int main() { LinkList L; InitList(L); }
從以上程式碼中,我們看到在定義結構體時,將struct LNode重定義為兩個名字:LNode
和*LinkList
之所以這樣命名,有助於我們後面對程式碼的理解。我們使用LNode
來定義結構體變數並統一指代連結串列中的一個結點,使用LinkList
定義指向結構體的指標並代表整個連結串列。
⭐上述表示定義了結構體struct LNode
,並且struct LNode
等價於LNode
,struct LNode *
等價於LinkList
。所以定義結構體變數可以採用struct LNode L
或者LNode L
;定義結構體指標變數時可以採用struct LNode *L
或者LNode *L
或者LinkList L
第二部分
現在有一個問題是為什麼InitList()
函式的形參為LinkList &L
?這對於不瞭解c++的我來說確實引發了一陣困惑。
⭐其實,在c++中LinkList &L
這種格式宣告的是一種特殊的型別---->引用型別,它直接以按引用呼叫的方式呼叫變數(有點類似於指標,但並不相同)。
舉個例子:
void swap1(int a, int b) { int temp = a; a = b; b = temp; } void swap2(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void swap3(int &a, int &b) { int temp = a; a = b; b = temp; } int main() { int a = 1, b = 2; swap1(a, b); // 按值呼叫 其結果仍然是a = 1, b = 2; swap2(&a, &b); // 通過指標模擬按引用呼叫,其結果為a = 2, b = 1; swap3(a, b); // 按引用呼叫,其結果為a = 2, b = 1; }
通過以上的解釋,我們就可以理解InitList(LinkList &L)
實際上是按引用呼叫了連結串列指標,這樣就可以將函式內對指標的修改帶回到主函式中。
那麼,如果我們不用這種方式,我們該怎麼做呢?
此時,我們就需要使用雙指標,程式碼如下:
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
bool InitList(LNode **L) { // 或者 InitList(LinkList *L)
(*L) = (LNode *) malloc(sizeof(LNode));
if ((*L) == NULL) {
return false;
}
(*L) -> next = NULL;
return true;
}
int main() {
LinkList L;
InitList(&L);
}
到此為止,我們就解釋了LNode
和LinkList
的具體使用情況(LNode宣告結構體變數,LinkList宣告結構體指標)以及C++中的引用型別。
第三部分
下面我們在舉一個靜態連結串列中的例子,深入理解一下。
先上程式碼:
#define MaxSize 10
typedef struct SNode{
ElemType data;
int next;
} SLinkList[MaxSize];
void testSLinkList() {
SLinkList a;
// 其他程式碼
}
---------------------------------
// 等價於
---------------------------------
# define MaxSize 10
struct SNode{
ElemType data;
int next;
};
void testSLinkList() {
struct SNode a[MaxSize];
// 後續程式碼
}
// 也就是說 struct Node a[MaxSize] <==> SLinkList a;
從上面我們總結出如下結論:
-
typedef .... *LinkList;
可以使簡化後續宣告結構體指標的過程,LinkList
就指代了一個結構體指標型別 -
typedef ..... LinkList[MaxSize];
可以使簡化後續宣告結構體陣列的過程,LinkList
就指代了一個結構體陣列型別
也就是說,我們通過typedef
生成了一個簡化版的新的資料型別。