在學習數據結構的時候,會常用到結構體。今天分享的內容是結構體與指針,由於結構體和指針自己的內容並非太多,因此今天的內容還包括了鏈表的實現。但願能夠經過這篇博客,讓你們熟悉結構體與指針,以及鏈表的實現。算法
1、結構體指針數組
1.一、結構體的簡單介紹數據結構
在實際應用過程當中,一組單一數據類型的數組很難知足咱們的需求,這個時候就須要藉助結構體。結構體是一種構造數據類型,它有許多不一樣數據類型的成員。假如咱們須要整理一個班級學生的數據,具體要整理的數據以下:ide
00後的人數學習
女生的人生ui
平均分數spa
排名前五的學生的姓名指針
面對這樣一個數據,沒法用基本數據類型的任何一個表示。可是咱們知道,要整理上面的數據須要知道下面幾個信息:code
生日regexp
性別
分數
姓名
因而咱們能夠根據這些信息,建立一個結構體。結構體的建立格式以下:
struct 結構體名稱{ 成員1 成員2 .....}
定義一個結構體的關鍵詞是struct,那麼學生結構體的建立以下:
struct student{ char name[20]; char sex[10]; int year; float score;}
1.二、結構體變量和結構體數組
結構體和普通變量有不少相似的地方,咱們能夠將結構體理解爲一個數組,一個存儲不一樣數據類型的數組(只是做爲理解,結構體和數組的操做徹底不一樣)。
(1)結構體變量
結構體變量的聲明和其它變量的聲明相似,大概樣式以下:
struct 結構體名稱 結構體變量;
那麼學生結構體變量聲明以下:
struct student stu1, stu2;
另外咱們能夠用typedef關鍵字來簡化結構體變量的聲明,具體操做以下:
//將類型struct student 定義爲 Student,之後看到了Student就能夠用struct student替換typedef struct student Student;
//那麼學生結構體的定義能夠變成以下Student stu1, stu2;
(2)初始化結構體變量
在結構體中,咱們能夠經過「.」來操做結構體的成員:
Student stu1;stu1.name = "zack";stu1.sex = "male";stu1.year = 1999;stu1.score = 89;
由於結構體是構造數據類型,它所佔的字節數是由每一個成員佔的字節數疊加的。
(3)結構體數組
結構體數組的定義和普通數組一致,咱們能夠循環初始化:
int i;Student stu[3];//循環輸入數據for(i = 0; i < 3; i++){ printf("請輸入姓名:"); scanf("%s", stu[i].name); printf("請輸入性別:"); scanf("%s", stu[i].sex); printf("請輸入年齡:"); scanf("%d", &stu[i].age); printf("請輸入分數"); scanf("%f", &stu[i].score);}//循環輸出結構體數組中的數據for(i = 0; i < 3; i++){ printf("*************************************"); printf("姓名:%s\n", stu[i].name); printf("性別:%s\n", stu[i].sex); printf("年齡:%d\n", stu[i].age); printf("分數:%f", stu[i].score);}
大體和普通變量沒有區別,操做結構體的關鍵就是「.」。
1.三、結構體指針
結構體指針和其它變量的指針相似,並且用結構體指針操做結構體的用法也相似,惟一的不一樣就是在用結構體指針操做結構體成員。
(1)結構體指針的定義
結構體指針的定義和普通指針變量的定義是類似的,在未使用typedef時,結構體指針定義以下:
struct 結構體名稱 *結構體指針變量名稱;//那麼學生結構體指針定義以下struct student *p;
而使用typedef以後,定義以下:
Student *p;
(2)結構體指針初始化結構體
在此以前先講一下訪問結構體成員的三種方式,假定有下列結構體和結構體指針:
//聲明一個結構體變量和結構體指針變量Student stu, *p;
那麼訪問成員的方式以下:
//經過「.」來訪問結構體成員,結構體變量訪問成員時,須要用「.」來訪問stu.name;//經過「->」來訪問成員,結構體指針訪問成員時,須要用「->」來訪問p->name;//先獲取結構體指針指向的內容,而後再訪問成員*p->name;
瞭解上面的東西后,就能夠知道結構體指針初始化結構體了。
Student *p;name = "zack";sex = "male";year = 1999;score = 89;
而後咱們作個簡單的練習,建立5個學生結構體,而後根據學生的年齡排名。爲了方便,咱們從新建立一個結構體:
typedef struct{ char name[20]; int age;}student;
這個結構體就兩個成員,咱們可使用冒泡排序:
//定義學生結構體數組,和臨時變量tempstudent stu[5], temp;int i, j;//循環輸入5個學生的信息for(i = 0; i < 5; i++){ printf("請輸入學生姓名:"); scanf("%s", stu[i].name); printf("請輸入學生年齡:"); scanf("%d", &stu[i],age);}//使用排序算法排序for(i = 0; i < 5; i++){ for(j = i; i < 5; j++){ if(stu[i].age > stu[j].age){ temp = stu[i] stu[i] = stu[j]; stu[j] = temp; } }}
能夠看到,結構體在按成員排序時和普通變量排序是一致的。
2、鏈表
以前說過指針在結構體中用處巨大,而這個用處實際體如今鏈表的實現。在具體講解鏈表前,先了解一下線性表的概念。
2.一、線性表
由於不是講解數據結構,因此對於線性表也是簡單介紹。
(1)線性表
其實咱們已經遇到過各類各樣的線性表,最典型的就是數組了。雖然數組不等同於線性表,可是用數組理解線性表是個很好的選擇。那麼數組有什麼特色呢?
數據集合
有序
每兩個相鄰元素之間都有對應關係
有開頭有結尾
由於數組和線性表仍是有區別的,因此並不表明上面的就是線性表的特色。不過有一點很是重要,就是「每兩個相鄰元素之間都有對應關係」,這個對應關係簡單來講就是「一個前驅一個後繼」。這麼說有點不理解了,通俗講就是「前面有一個,後面有一個」。這裏的一個是指最多一個,也能夠是零個。就比如珍珠項鍊,你任意以一個珍珠做爲參考,任何一個珍珠都是前面一個,後面一個。
(2)順序表和鏈表
上面簡單說了一下線性表,而後咱們來說講線性表和鏈表的關係。先看下面兩張圖:
第一個是鐵鏈,第二個並非麻花啊,它是一條繩子。我說這兩個都符合線性表的特色你們可能不是很理解,對於鐵鏈還能夠接受,可是繩子就有點牽強了。因此咱們假設,繩子上面串了珍珠。
在假設繩子串珍珠以後,會發現鐵鏈和繩子都符合「前一個後一個」的標準。咱們也不深刻研究了,如今我告訴你們這兩個都是線性表。可是它們有什麼區別呢?咱們先看看鐵鏈的特色:
能夠任意加長
在中間添加鏈子很是方便
而後咱們看看繩子:
不能加長
在中間添加珍珠要移動後面全部珍珠
這麼一看鏈子要厲害許多,可是這只是對於鏈子和繩子來講。實際上鍊表和順序表並不徹底和上面同樣。舉這個例子只是做爲直觀的理解,鏈表具體的特色,我將在鏈表的實現當中爲你們講解。
2.二、鏈表介紹
(1)鏈表的實現原理
鏈表其實是由一個個節點組成的,每一個節點都存儲兩個東西。一個數據、還有一個地址。數據的話就是咱們要用到的東西,地址存儲的是下一個節點的地址。這樣咱們就能經過某一個節點找到下一個節點,僅此而已。
(2)用結構體模擬節點
結構體是一種構造數據類型,能夠有許多類型不一樣的成員。而後咱們根據節點的特色就能夠用結構體模擬出一個節點了。
開始說節點存儲兩個數據,其實不許確。應該是兩種數據,一個是咱們要用到的數據,還有一個是下一個節點的指針。存放數據的區域叫作數據域,存放地址的區域叫作指針域。咱們先來定義一個最簡單的節點:
typedef struct num{ //數據域 int data; //指針域 struct num *next;}Node, LinkedList;
首先數據域沒有什麼疑問,就是一個普通的int數據。而後是指針域,由於咱們是要存儲下一個節點的地址,而節點又是一個num結構體,而後咱們就能夠根據上面學的結構體指針定義的方式定義一個結構體指針。
注意:在結構體中,內存大小必須是肯定的。結構體的成員不容許是自己結構體變量,可是能夠爲自己的結構體指針。覺得指針的大小是肯定的,而若是成員中有自己的結構體變量系統將沒法知道這個結構體應該分配多少內存。
結構體的具體實現將在下一篇爲你們分享。
https://mp.weixin.qq.com/s/wmCT8PoJBtewhGw0liczbg