c語言數據結構(二)----線性錶鏈式存儲結構及運算實現(單鏈表篇)

上回我們學習了用數組構造順序表,順序表申請的一塊數組地址是連續的,這次我們學習用指針構造鏈表,這時所構造的鏈表地址不一定是連續的,比較活用。

鏈表分爲單鏈表循環鏈表雙向鏈表

今天先來碼單鏈表,鏈表可以帶頭結點,也可以不帶頭結點,帶頭結點更方便插入、刪除的運算,所以我選擇了帶頭結點。

  • 不帶頭結點的單鏈表

不帶頭結點的單鏈表

  • 帶頭結點的單鏈表

帶頭結點的單鏈表

/*頭文件及宏定義*/
#include<stdio.h>
#include<stdlib.h>
typedef int datatype;
typedef struct node	    //定義結點
{
    datatype data;          //數據域
    struct node *next;      //指針域
}LNode;

鏈表的建立

鏈表建立可以用兩種方法:頭插法尾接法

  • 頭插法:在鏈表頭一個元素結點前插入新的元素,這樣插入的鏈表元素是倒着 的順序。

頭插法

  • 尾接法:在鏈表的尾結點後新增元素,這樣建立的鏈表是順着的。
    尾接法
//頭插法(往首元素前面插,倒着創建)
LNode *CreateLinkList1()
{
    LNode *head,*p;                         //head爲鏈表的頭指針,p爲鏈表的暫存指針
    int x;
    head=(LNode *)malloc(sizeof(LNode));    //生成頭結點
    head->next=NULL;
    printf("請輸入單鏈表元素:");
    scanf("%d",&x);
    while(x!='\n')
    {
        p=(LNode*)malloc(sizeof(LNode));    //申請新結點
        p->data=x;                          
        p->next=head->next;                 //新結點指向頭元素的結點
        head->next=p;                       //head指向新結點
        scanf("%d",&x);
    }
    return head;
}
//尾接法(在最後一個元素末尾插,順着建立)
LNode *CreateLinkList2()
{
    LNode *head,*p,*q;                      //head爲鏈表的頭指針,p爲鏈表的暫存指針,q爲指向末尾結點的指針
    int x;
    head=(LNode *)malloc(sizeof(LNode));    //生成頭結點
    head->next=NULL;
    q=head;                                 //在鏈表沒有元素的情況下可以尾指針q可以看作是頭指針
    printf("請輸入單鏈表元素:");
    scanf("%d",&x);
    while(x!=-1)                            //輸入-1則停止
    {
        p=(LNode*)malloc(sizeof(LNode));    //申請暫存結點空間
        p->data=x;
        p->next=NULL;
        q->next=p;                          //將鏈表連接起來
        q=p;                                //q指向最新的結點,即尾結點
        scanf("%d",&x);
    }
    return head;
}
//求表長
int Length_LinkList(LNode *head)
{
    LNode *p=head;
    int i=0;
    while(p->next!=NULL)
    {
        p=p->next;
        i++;
        //printf("%d %c\n",i,p->data);		用來測試
    }
    return i;
}

查找運算

查找頭結點爲head的鏈表第i個元素

//按位置查找
LNode *Get_LinkList(LNode *head,int i)
{
    LNode *p=head;
    int j=0;
    while(p->next!=0&&j<i)
    {
        j++;
        p=p->next;
    }
    if(i==j)                                 //若找到則返回指針值,否則返回空值
        return p;
    else
        return NULL;
}

插入運算

在第i個位置插入元素x

//插入運算
void Insert_LinkList(LNode *head,int i,int x)//head指向頭結點,i爲插入的位置,x爲插入的值
{
    LNode *p,*q;
    q=Get_LinkList(head,i-1);               //找到要插入結點的前一個位置
    if(q==NULL)
        printf("位置非法,無法插入");
    else
    {
        p=(LNode*)malloc(sizeof(LNode));    //申請結點空間
        p->data=x;
        p->next=q->next;                    //插入結點
        q->next=p;
    }
}

刪除運算

刪除第i個元素,這裏運用free()函數釋放內存空間

//刪除運算
void Del_LinkList(LNode *head,int i)        //head指向頭結點,i爲要刪除的結點位置
{
    LNode *p,*q;
    q=Get_LinkList(head,i-1);               //找到要刪除結點的前一個位置
    if(q==NULL)
        printf("刪除位置非法!");
    else
    {
        p=q->next;                          //p指向要刪除的i結點
        q->next=p->next;                    //從鏈表中刪除第i個結點
        free(p);                            //釋放第i個結點的存儲空間
    }
}

調試代碼

int main()
{
    /*建立鏈表並輸出*/	 
    LNode *head,*p,*q;
    head=CreateLinkList2();
    p=head;					//使p指向頭結點,以下操作皆是
    printf("表長爲:%d\n",Length_LinkList(p));
    p=p->next;
    printf("鏈表元素爲:");
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    /*查找*/
    int a;
    printf("請輸入要查找的元素位置:");
    scanf("%d",&a);
    p=head;
    q=Get_LinkList(p,a);
    if(q!=NULL)
        printf("元素值爲:%d",q->data);
    else
        printf("該元素不存在!");
    /*插入(用時取,不用則註釋掉)*/
    p=head;
    int i;
    int x;
    printf("請輸入要插入的位置:");
    scanf("%d",&i);
    printf("請輸入要插入的元素值:");
    scanf("%d",&x);
    Insert_LinkList(p,i,x);
    /*刪除(用時取,不用則註釋掉)*/
    p=head;
    int i;
    int x;
    printf("請輸入要刪除的位置:");
    scanf("%d",&i);
    Del_LinkList(p,i);
    /*輸出*/
    p=head;
    printf("表長爲:%d\n",Length_LinkList(p));
    p=p->next;
    printf("鏈表元素爲:");
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    return 0;
}

總結
這裏的鏈表確實考驗對指針的理解,我也是思考了很久才得出可以讓自己信服的解釋,指針指向一個結點,其中p=head我想了很久,其含義爲p指針指向head指針指向的地址,這是和小夥伴討論了許久纔得到的答案。懂得了指針的含義,鏈表也就很容易地寫出來了。

循環鏈表由於只是在單鏈表的基礎上,將尾結點指向頭結點,所以就不再多加贅述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章