鏈表和數組的不同點在於:數組裏所有的元素的地址都是連着的,不能分散着。而鏈表是可以分散的。但是鏈表和數組也各有各的優點。數組的優點就是佔用的內存小,鏈表的優點是內存可以不是整塊的使用,可以使用一些分散的內存塊,這樣可以有效的利用內存來記錄數據。
比如,綠色的就是用的數組的方式,四個元素只需要四個存儲單元,但是你用鏈表就需要8個存儲單元,但是這8個可以不連續的,但是那兩個還是必須連續的,所以一個結構體內有多個數據的話,內存使用效率就會提高,不過一個結構體內的數據域和指針域還是必須連着的。在數據比較多複雜的時候就可以用鏈表,它可以把各個散落的存儲單元利用起來,提高了利用效率。
靜態鏈表
typedef struct student
{
int score;
struct student *next; //創建一個鏈表,包含數據和指針
} LinkList;
```這是一個結構體,包含一個數據和一個指針
我們可以定義三個靜態鏈表
```cpp
int main()
{
LinkList node1={1,NULL}; //創建三個結構體
LinkList node2={2,NULL};
LinkList node3={3,NULL};
node1.next=&node2; //第一個結構體內的指針指向第二個結構體地址
node2.next=&node3;
node3.next=NULL;
LinkList *head=&node1; //創建一個頭結點
while(head != NULL) //遍歷鏈表,可以用來查詢鏈表數量
{
printf("data:%d\n",head->score);
head=head->next; //這個指針等於指向下一個結構體的指針
}
}
這樣雖然只有三個數據,但是指針也會佔用存儲單元,相當於一共佔用了6個存儲單元,是數組的兩倍。推薦數據量小就用數組。實際過程中,鏈表一般是動態的,我們需要對數據刪除,增加等等。。。
動態鏈表
其實我覺得動態鏈表和靜態鏈表差不多,就是在增加和刪除節點的時候用靜態鏈表更容易理解,動態鏈表則難一點:
創建結構體,一個數據域一個指針域還是一樣的
typedef struct student
{
int score;
struct student *next; //創建一個鏈表,包含數據和指針
} LinkList;
然後我們先循環創建一個鏈表
創建鏈表
//創建一個列表
LinkList *CreateList(int n)
{
int i;
LinkList *head,*node,*end; //定義一個頭結點
head=(LinkList*)malloc(sizeof(LinkList)); //給頭結點申請內存
end=head; //這個爲什麼頭結點等於
//尾結點,這是因爲鏈表還沒有創建,所以是沒有數據的,所以頭結點就等於尾結點
//我是這麼理解的,剛學
end->next=NULL; //鏈表最後一個結點的指針爲空
for(i=0;i<n;i++) //循環創建鏈表
{
node=(LinkList*)malloc(sizeof(LinkList));
node->score=i; //給結點數據賦值
end->next=node; //這個node是新申請的節點
//而end是最後一個結點,最後一個結點指向新申請的那個結點,我的理解
node->next=NULL;
end=node;
}
return head;
}
增加結點
這個增加結點的時候,需要定義兩個結構體,其中一個是新申請的節點,另外一個結點是用來交換的,如果沒有這個結點,鏈表會不停的指向結點,相當於循環一樣。
如果只定義一個結構體的話,我的理解是這麼寫的`
node->next=now;
now->score=mem; //賦值於新的節點的數據值
now->next=node; //now的下一個指針指向node
但這樣不行,他會一直在那個結點和增加的節點循環,相當於,所以就需要定義兩個結構體,其中一個用來交換,避免出現這種情況。
//插入在第幾個節點,比如5,插入的節點就是第五個節點
int insert(LinkList *head,int num,int mem)
{
int i=0;
LinkList *node=head;
LinkList *swap; //用於交換
LinkList *now; //存入的節點
now=(LinkList*)malloc(sizeof(LinkList));
while(i<num-1) //比如back=5,執行四次,此時循環後是第四個node
{
i++;
node=node->next;
}
now->score=mem; //賦值於新的節點的數據值
swap=node->next; //sw下一個指針指向swap
node->next=now; //node 下一個指針指向now
now->next=swap; //now的下一個指針指向swap
return 0;
}
刪除節點
int dele(LinkList *head,int back)
{
int data,i=0;
LinkList *node=head;
LinkList *now;
while(i<back-1) //比如back=5,執行四次,此時循環後是第四個node
{
i++;
node=node->next;
}
now=node->next; //now等於第五個node的指針 ,這兩個是爲了釋放第五個node的內存
node->next=node->next->next;
free(now);
return 0;
}
刪除指針就比較簡單了,直接講第n個指針指向低n+2個指針,就可以了,然後釋放那個結點的內存就好了
遍歷鏈表
用來打印鏈表內的數據
void traverlist(LinkList *head)
{
LinkList *p=head->next;
while(NULL!=p)
{
printf("該節點數值爲:%d\n",p->score);
p=p->next;
}
return;
}
主函數裏面就調用這些函數就好了
int main()
{
LinkList *phead;
phead=CreateList(5);
traverlist(phead);
printf("111111111111111111111111111\n");
dele(phead,2);
traverlist(phead);
printf("111111111111111111111111111\n");
insert(phead,3,111);
traverlist(phead);
}