實驗一:鏈表的基本操作


預備知識

你們的每一次瀏覽都是我堅持寫下去的動力

結構體

C語言的數據類型包括基本數據類型、構造型據類型指針類型和無類型;基本數據類型有整型、實型、字符型、枚舉;構造數據類型包括數組、結構體、公用體;結構體可以有基本數據類型與指針類型組合而來,主要用來表示鏈表、棧、樹等較為復雜的數據對象。

  • 基本格式

    以學生信息為例

    struct student
    {
      char sex;               //數據域
      int age;
      struct student *next;   //指針域
    };                       //結構體要以分號結束
    

    鏈表的一個結點就表示一個結構體對象,包括數據域可指針域;指針next指向下一個節點的地址;

  • typedef運算符

    簡單理解就是typedef可以為已有的數據類型起一個新名字

    //給int起個新名字叫INTER
    typedef int INTER;    
    int e=10;    INTER e=10;  //等價
    

    同理,也可以為結構體起一個新名字,以方便代碼書寫,並且可以使代碼簡潔易讀

    typedef struct student
    {
      char sex;             
      int age;
      struct student *next; 
    }STUDENT;
    

全局變量

簡單講,在函數體內定義的叫做局部變量,包括主函數,在函數體外定義的即為全局變量;全局變量的特點有一下幾點

  • 存儲在C語言內存結構中的靜態存儲區
  • 所有函數都可以訪問並改變其值
  • 可以在主函數內定義局部變量通過向自定義函數傳參的方式代替全局變量
int e=10;     //全局變量
int main()
{
  int m=20;   //局部變量
  printf("%d  %d",e,m);
}
// 10  20

指針

  • 指向結構體的指針

    typedef struct student
    {
      char sex;              
      int age;
      struct student *next;
    }STUDENT;
    STUDENT *p;  //指針p指向結構體STUDENT
    
  • 指向結構體變量的指針

    typedef struct student
    {
      char sex;              
      int age;
    }STUDENT;
    STUDENT stu1,stu2,stu3;   //定義三個對象,分別代表學生1、2、3
    STUDENT *p;               //此時p未初始化,指向一個隨機值,因此需要對指針初始化 
    p=&stu1;                  //把學生1的地址賦給p
    

    由於鏈表所用的結構體設置了指針域,由指針域指向下一個結點,實際上並不需要指向結構體變量的指針

代碼解析

  • 創建鏈表

    #include<stdio.h>
    #include<stdlib.h>
    
    typedef struct LNode
    {
        char date;
        struct LNode *next;
    }LNode;
    
    LNode *head; //定義鏈表頭指針  
    int n;       //n用來存放鏈表結點個數
    

    上述代碼中,頭指針與結點個數設置為全局變量,因為鏈表不是隨機存儲結構,必須要通過頭指針來訪問其他結點,在對鏈表進行插入、刪除等操作時,各功能函數都需要獲取頭指針;

  • 插入操作

    //插入元素e到表尾
    void Insert_end()
    {
        char e;
        LNode *p,*p_new = NULL;
        p=head;
        printf("請輸入要插入的元素:\n");
        scanf("%c",&e);
        for(int i=0;i<n;i++)    //通過for循環,是p指向最后一個結點
        {
            p=p->next;
        }
        p_new=(LNode *)malloc(sizeof(LNode)); //為新添的節點分配空間
        if(p_new==NULL)
        {
            printf("內存分配失敗!\n");
            exit(0);
        }
        p_new=p;       
        p_new->date=e;
        p_new->next=NULL;
        n++;
    }
    
    //插入元素e到表頭
    void Insert_head()
    {
        
        char e;
        printf("請輸入元素:\n");
        getchar();  //吃掉緩沖區的回車鍵,一定要加這一句,不然很慘的
        scanf("%c",&e);
        LNode *p,*p_new;
        p=head;
        p_new=(LNode *)malloc(sizeof(LNode));
        if(p_new==NULL)
        {
            printf("內存分配失敗!\n");
            exit(0);
        }
        p_new->next=p;
        p_new->date=e;
        p=p_new;
        head=p;     //使head重新指向頭指針
        n++;
    }
    
  • 對於元素的插入,可以插入到表頭,表尾,或是某個元素之后,如果把每種情況都寫成一個函數太過繁 瑣,因此下面的完整代碼中,把三種情況整合到一個函數中

完整代碼

程序運行界面比較簡單,我覺得重在算法的理解

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
    char date;
    struct LNode *next;
}LNode;

LNode *head;
int n;

//創建鏈表並輸入元素
void create()
{
    char e;             //用來暫時存放你從鍵盤輸入的元素
    LNode *p,*p_new;    //p指向當前最后一個結點,p_new指向新插入的結點
    head=(LNode *)malloc(sizeof(LNode));  //為頭指針指向的頭節點開辟空間
    if(head==NULL)
    {
        printf("內存分配失敗!\n");
        exit(0);
    }
    p=head;         //將頭結點的地址賦給p,用p代替head,因為鏈表為空時,頭結點也是最后一個結點
    printf("請輸入元素!\n");
    for(int i = 0;;i++)  
    {
        p_new=(LNode *)malloc(sizeof(LNode));
        if(p_new==NULL)
        {
            printf("內存分配失敗!\n");
            exit(0);
        }
        scanf("%c",&e);
        n++;          //更新鏈表元素個數
        p->next=p_new;//將新結點的地址賦給最后一個結點的指針域
        p->date=e;    //將從鍵盤輸入的元素e存放到上個結點的數據域
        p_new->next=NULL; 
        p=p_new;     //使p重新指向最后一個結點
        if(getchar()=='\n')
        {
            break;
        }   
    }
  free(p);  //上面代碼執行完畢后,實際上最后一個結點是空的,因為數據都是存放在倒數第二個結點的數據域(p->date=e),因此應該釋放最后一個結點占用的內存空間
}
//顯示鏈表中所有元素
void Output()
{
    LNode *p;
    p=head;
    printf("鏈表中的元素為:\n");
    for(int i=0;i<n;i++)
    {
        printf("%c ",p->date);
        p=p->next;
    }
    printf("\n");
}
//插入元素e到首、尾、第i個元素后面
void Insert_i()
{
    int t;      //t用來存放插入的位置信息
    char e;
    LNode *p,*p_new;
    p=head;
    p_new=(LNode *)malloc(sizeof(LNode));
    if(p_new==NULL)
    {
        printf("內存分配失敗!\n");
        exit(0);
    }
    printf("請輸入位置i和元素e:\n");
    scanf("%d",&t);
    getchar();    
    scanf("%c",&e);
    //插入到表頭
    if(t==0)
    {
        p_new->next=p;
        p_new->date=e;
        p=p_new;
        head=p;
        n++;
    }
    //插入到表尾
    else if(t==n)
    {
        for(int i=0;i<n;i++)
        {
            p=p->next;
        }
        p_new=p;
        p_new->date=e;
        p_new->next=NULL;
        n++;
        
    }
  //插入到某個元素的后面
    else
    {
        for(int i=0;i<t-1;i++)
        {
            p=p->next;
        }
        p_new->next=p->next;
        p->next=p_new;
        p_new->date=e;
        
        n++;
    }
}

//刪除指定元素
void delete()
{
    char e;
    int n;
    LNode *p;
    p=head;
    printf("請輸入需要刪除的元素的位置: ");
    scanf("%d",&n);
    if(n==1)
    {
        head=p->next;
    }
    else{
       for(int i=0;i<n-2;i++)
       {
           p=p->next;
       }
       e=p->next->date;
       p->next=p->next->next;
       n--;
    }
  free(p);
}

//菜單
void menu()
{
    
    printf("\t\t\t* 1-輸入\n\t\t\t* 2-插入\n\t\t\t* 3-刪除\n\t\t\t* 4-輸出\n\t\t\t* 0-退出\n");
    
}

int main()
{
    head=NULL;
    int choose;
    menu();
   while(1)
   {
       printf("%c親,請開始你的操作:",0);
       scanf("%d",&choose);
       getchar();     //吃掉你輸入后按下的回車鍵
       if(choose==0)
           exit(0);
       else
       {
           switch (choose) {
               case 1:
                   create();
                   break;
               case 2:
                   Insert_i();
                   break;
               case 3:
                   delete();
                   break;
               case 4:
                   Output();
                   break;
               default:
                   break;
           }
       }
       
   }
    return 0;
}

聯系作者 QQ:749866529


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM