「data structure」的圖片搜尋結果

資料結構複習(三): 結構、結構指針

LUFOR129
7 min readSep 20, 2018

我們來到結構章節,用樂高積木做比喻,好比做積木模具。這個章節內容會比較多,不過也算是基礎中的基礎,會講述到比較偏實作的東西。此外也會講解到動態儲存分配malloc、類型定義typedef。等這個章節學完後就能開始進入做積木的階段了!

結構 Struct

在真實世界中,面對的複雜度往往不是一個數、一個字串,而是一群數據的集合。好比說我自己身上的數據,可以寫成如下:

int age=20;
int grade=3;
String Name="Lufor129";
boolean boy=true;
char addr[30];
... //我是一群數據的集合

但C並沒有像JAVA的物件的概念,取而代之的是結構

struct Student{
int age;
boolean boy;
char Name[30];
}; //記得加分號,我每次都忘記

之後可以使用宣告的結構來實例化"物件",訪問方法則是 物件變數.結構名,當然你也可以建立一個結構數組則訪問變成 物件變數[下標].結構名。基本上請將你建立的結構當成是一種自己建立的數據類型。

結構不僅可以做為函數參數,也可為函數返回值

建立與訪問:Student lufor129;
lufor129.age=20;
lufor129.boy=true;
printf("%d",lufor129.age); //20
printf("%d",lufor129.boy); //true
作為函數返回值:Student newStudent(int age,boolean boy){
Student temp={age,boolean};
return temp;
}
int main(){
Student A=newStudent(18,false);
printf("%d",A.age); //18
return 0;
}

結構指針

結構指針,顧名思義就是指向結構的指針。使用結構指針可以透過指針更方便的直接訪問結構成員,同時結構指針也可做為參數傳遞。具體有兩種訪問方式:

  1. 用*訪問 : *(結構指針變量).結構成員名
  2. 用 — >訪問 : 結構指針變量->結構成員名
Student *ptrToStudent=&lufor129;
printf("%d",ptrToStudent->age); //20
printf("%d",*(ptrToStudent).age); //20

指針沒學好的同學現在應該暈了,其實你就看做是新一個簡單的訪問結構成員。可以回去重看一次指針的章節喔!!

那麼問題來了結構指針具體能夠用在哪裡呢?

power by 小畫家,因為只會用小畫家

答案是可以用結構指針in結構中,讓結構可以指向另一個結構,有趣吧!!最後能串起來形成鏈表(Linked List),不過更具體留在下一章節,這章節先來小試身手。

struct Link{
int data;
Link *ptrToLink;
};
//單一鏈表結構
Link newLink(int data){
Link tempLink;
tempLink.data=data;
tempLink.ptrToLink=NULL;
return tempLink;
}
//建立鏈表節點的函數
int main(){
Link A = newLink(9);
Link B = newLink(20);
Link C = newLink(21);
A.ptrToLink=&B;
B.ptrToLink=&C;
printf("%d\n",A.ptrToLink->data); //20
printf("%d\n",A.ptrToLink->ptrToLink->data); //21
return 0;
}

可以仔細看看,為什麼會印出20,21,也可以自己試驗一些程式。

動態儲存分配Malloc

C語言的動態記憶體分配可以讓程式在需要大量記憶體或需要記憶體數量不固定時動態的取得記憶體,方法malloc 存在於stdlib.h,先來看看函數的宣告。

void *malloc(unsigned size);
//可以看出,回傳的是指針而傳入的是大小(unsigned變量類型)
//成功則返回分配空間的起始地址,失敗則回傳NULL

試試看來分配一陣列,我們知道陣列其實本質是連續的指針,因此我們利用指針建立陣列,這部分稍微難點:

int *arr;       //宣告指針,是一個指向int的指針,但目前沒分配空間
int Length=10; //想要分配的長度
arr=(int *)malloc(Length*sizeof(int));
//現在已知返回的會是void,因此用(int *)將他改成int指針
//已知sizeo(int)=4; Length為10; 因此*arr應該會==arr[10]
//現在來驗證看看
for(int i=0;i<Length;i++){
arr[i]=i;
printf("%d\n",arr[i]);
}
// 0,1,2,.....9 成功動態分配長度為10int的陣列

由於在結構中,常常會需要用到malloc來建立新的結構物件,例如:

Student newStudent=(Student *)malloc(sizeof(struct Student));

類型定義Typedef

typedef,其實說白了,就是取新名字,可能有人問說,取新名字有什麼重要的? 確實,不用typedef也可以寫得出來,但typedef可以讓你在寫的過程中更清晰,更直觀。

語法很簡單: typedef 原有類型名 新類型名
typedef int ElementType;
printf("%d",sizeof(ElementType)); //4
//把int 建新綽號叫 ElementType

這到底有什麼用呢?常用在不確定數據的類型,如期末成績,到底要用float?還是int ? 甚至用 double。 更常的時候可以用在建立指針的類型,不讓程式滿* 到處飛。

typedef int * IntPointer;
IntPointer I=&B; //等同於 int *I=&B;
typedef struct Node * PtrToNode; //建立指向struct Node 的指針類型
struct Node {
ElementType data;
PtrToNode Next;
}
// 可以簡單的建立一個串鏈結構

參考資料

  1. https://blog.gtwang.org/programming/c-memory-functions-malloc-free/
  2. https://noob.tw/data-structure-adt/
  3. https://www.icourse163.org/course/ZJU-93001
  4. 《数据结构》(第2版),陈越、何钦铭、徐镜春、魏宝刚、杨枨 编著,高等教育出版社,2016年6月

--

--