<address id="ousso"></address>
<form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
  1. C語言

    c語言鏈表的用法

    時間:2025-03-10 17:38:01 C語言 我要投稿

    c語言鏈表的用法

      鏈表是數據結構中比較基礎也是比較重要的類型之一,那么有了數組,為什么我們還需要鏈表呢!或者說設計鏈表這種數據結構的初衷在哪里?下面小編就為大家介紹下c語言鏈表的用法。

      c語言枚舉的用法如下:

      這是因為,在我們使用數組的時候,需要預先設定目標群體的個數,也即數組容量的大小,然而實時情況下我們目標的個數我們是不確定的,因此我們總是要把數組的容量設置的很大,這樣以來就浪費了很多的空間。另外,數組在進行插入操作和刪除操作的時候,在插入或者刪除制定元素之后,我們往往需要進行循環移位,這增加了我們的線性開銷。

      正是由于以上的兩種主要原因,鏈表被設計出來用于一般表的操作。為了避免上面描述數組的兩種弊端,我們希望鏈表有一下的特點

      1 可以靈活的擴展自己的長度。

      2 存儲地址不連續,刪除或者插入操作的時候不需要循環移位。

      要實現以上兩個特點,我們需既要保證每個節點的獨立性,又要保存相鄰兩個節點的聯系。

      為此,鏈表一般被設計為下面的形式。

      Node--->Node---->Node

      鏈表是由一個一個的節點組成的,可以方便和自由的插入未知個Node,前一個節點中用指針保存著下一個節點的位置,這樣以來便順利的完成了我們對鏈表的兩點期望,但是唯一的缺點是增加了額外的空間消耗。

      ————————————————————————————————————————————————————————————————————————————

      鏈表的定義:

      鏈表的定義一般使用結構體,在看《數據結構與算法分析》這本書的時候發現,書中頻繁的使用typedef的關鍵字,結果真的很棒不僅保持的代碼的整潔程度,也讓我們在下面的編碼過程中少見了很多煩人的指針(當然指針還是一直存在的)。所以這里也借用了書中的定義方法。

      struct Node;

      typedef struct Node* PtrNode;

      typedef PtrNode Position;

      typedef PtrNode List;

      struct Node{

      int Value;

      PtrNode Next;

      };

      下面接著書寫一個建立鏈表的函數,輸入每個節點的值,直到這個值是-1的時候函數結束。

      在這個里面,我以前一直搞不明白為什么需要定義三個Node *,現在終于了解了,最終還是復習了指針的內容明白的,這里說一下指針實現鏈表對指針的操作很頻繁,需要比較扎實的掌握了指針之后,在來看鏈表會輕松很多。在下面的一段程序里,我分別定義了head/p/tmp這三個指向節點結構體的指針,head的主要作用就像一個傳銷頭目,他會主動聯系上一個下線p,然后他就什么也不干了,p接著去發展一個又一個的下線tmp,結果一串以head為首的鏈表就出來了。

      起先,我總覺得有了head,為什么還要p,這是因為如果直接使用head去指向下一個節點,head的位置也是不斷在移動的,即它永遠處于鏈表的尾端,這樣當我們返回鏈表的時候,其實是空值。所以,我們需要p這個中轉環節。(其實,這種做法在指針中非常普遍,大部分有返回指針類型的函數中,都會首先定義一個指針變量來保存函數的傳入的參數,而不是對參數直接進行操作)。

      ?

      /*

      函數功能:創建一個鏈表

      函數描述:每次輸入一個新的整數,即把新增加一個節點存放該整數,

      當輸入的整數為-1時,函數結束。

      */

      List create()

      {

      int n=0;

      Position p,head,tmp;

      head=NULL;

      tmp=malloc(sizeof(struct Node));

      if(tmp==NULL)

      {

      printf("tmp malloc failed! ");

      return NULL;

      }

      else

      {

      p=tmp;

      printf("please input the first node's message! ");

      scanf("%d",&(tmp->Value));

      }

      while(tmp->Value!=-1)

      {

      n+=1;

      if(n==1)

      {

      head=p;

      tmp->Next=NULL;

      }

      else

      {

      p->Next=tmp;

      }

      p=tmp;

      tmp=malloc(sizeof(struct Node));

      printf("please input the %d node! ",n+1);

      scanf("%d",&(tmp->Value));

      }

      p->Next=NULL;

      free(tmp); //free函數free掉的只是申請的空間,但是指針還是依然存在的。

      tmp=NULL;

      return head;

      }

      接下來,在寫一個刪除鏈表節點的函數,輸入一個整數然后遍歷鏈表節點,當鏈表節點的值與該整數相等的時候,即把該節點刪除。

      在完成這個函數首先一定要把這個過程思考清楚,不可否認我之前是一個上來就敲代碼的人,看了《劍指offer》感覺這種習慣是程序員的大忌,甚至還想寫一篇博客,名字都想好了《程序員的自我修養之思考在前,代碼在后》。其實想想也是,我們寫程序的目的是為了解決問題,而不是為了簡單的寫程序,純粹的讓程序跑起來大概只會在上學那會存在吧!真實的程序開發中需要考慮幾乎所有 能想到的實際問題,所以無論程序再下,一要學會先思考清楚,再下筆寫程序。

      關于這個函數,我們要想到的是:

      1 如果鏈表為空,我們該怎么做,當然是直接返回。

      2 如果要刪除的元素為頭節點該怎么辦?

      3 如果要刪除的元素為尾節點該怎么辦?

      當注意到以上三個部分,我們的程序就可能避免掉了輸入鏈表為空,程序直接崩潰的現象,也可以避免刪除元素值為頭節點時刪不掉的尷尬。我們的程序就有了一定的魯棒性。

      下面著重考慮鏈表的刪除的實現:

      list: ???? Node_a->Node_b->Node_c->Node_d;

      ?????????????? list ?????? tmp???????? p

      ?

      ?? -------> ?????? ? ? ? tmp->Next=p->Next;

      ?

      ?

      list:?????? Node_a->Node_b----------->Node_d

      ????????????????????????????????????? free(p)

      假設我們要刪除的節點為上圖的Node_c;假設我們能夠找到Node_c的前一個位置tmp和被刪除節點位置p的話;這個時候我們只需要執行tmp->Next=p->Next即可。

      只要完成上面的分析以及考慮到各種情況,我們完成下面的代碼就水到渠成了。

      /*

      函數功能:刪除鏈表中指定值的節點(如果存在多個,只刪除第一個)

      本例中輸入一個整數,刪除鏈表節點值為這個整數的節點。

      */

      List DeleteNode(List list)

      {

      Position p,tmp;

      int value;

      if(list==NULL)

      {

      printf("The list is null,function return! ");

      return NULL;

      }

      else

      {

      printf("please input the Node's value: ");

      scanf("%d",&value);

      }

      p=list;

      if(p->Value==value)

      {

      list=p->Next;

      free(p);

      p=NULL;

      return list;

      }

      while(p!=NULL&&p->Value!=value)

      {

      tmp=p;

      p=p->Next;

      }

      if(p->Value==value)

      {

      if(p->Next!=NULL){

      tmp->Next=p->Next;

      }

      else

      {

      tmp->Next=NULL;

      }

      free(p);

      p=NULL;

      }

      return list;

      }

      ?關于鏈表的使用場景分析:

      鏈表在程序開發中用到的頻率還是非常高的,所以在高級語言中往往會對鏈表進行一些實現,比如STL中list以及Java中也有類似的東西。在目前的服務器端開發,主要運用鏈表來接收一些從數據中取出來的數據進行處理。

      即使你不知道鏈表的底層實現,仍然可以成功的運用STL里面的現成的東西。但是作為一個學習者,我覺得會使用和從底層掌握仍然是兩個不同的概念,linux之父說:“talk is less,show you code”。

      以下的程序,用鏈表模擬了一個電話通訊錄的功能,包括添加聯系人,查找聯系人,以及刪除聯系人。

      PS:關于魯棒性,程序中最大的危險是使用了gets這個函數,目前先保留使用gets,等待找到工作之后在做進一步的程序完善。(尼瑪,讀書去。。。應屆生,找個工作他媽咋這么難呢!?? 工作經驗,工作經驗,艸,那個大牛一出校門就什么都會。)

      ?

      /**************************************************************************

      Programe:

      This is a phone list write by list

      The programe is just prictise for list

      Author: heat nan

      Mail:964465194@qq.com

      Data:2015/07/27

      **************************************************************************/

      #include

      #include

      #include

      #define N 25

      #define M 15

      struct node;

      typedef struct node* p_node;

      typedef p_node List;

      typedef p_node Position;

      typedef struct node** PList;

      struct node{

      char name[N];

      char number[M];

      Position next;

      };

      int JudgeNameExist(List list,char* name);

      void AddPerson(PList list);

      void PrintList(List list);

      List FindPerson(List list);

      List FindPersonByName(List list,char* name);

      int AddPersonByName(PList list,List node);

      int DeletePersonByName(PList list,char* name);

      void DeletePerson(PList list);

      int main()

      {

      List list=NULL;

      Position p;

      char cmd[100];

      while(1)

      {

      printf("   MAIN   ");

      printf(" ******* 1 add a person ******* ");

      printf(" ******* 2 show the phone list ******* ");

      printf(" ******* 3 find from phone list ******* ");

      printf(" ******* 4 from phone list ******* ");

      printf("Please input the cmd number: ");

      gets(cmd);

      switch(cmd[0])

      {

      case '1':

      AddPerson(&list);

      break;

      case '2':

      PrintList(list);

      break;

      case '3':

      FindPerson(list);

      break;

      case '4':

      DeletePerson(&list);

      break;

      default:

      printf("wrong cmd! ");

      break;

      }

      }

      return 0;

      }

      /*

      Function:判斷要添加的聯系人名稱是否已經存在于電話簿中.

      Input: List 電話列表,name 要添加的聯系人的姓名.

      Return: 已經存在返回1,不存在返回0.

      */

      int JudgeNameExist(List list,char* name)

      {

      if(FindPersonByName(list,name)!=NULL)

      return 1;

      else

      return 0;

      }

      /*

      Function:根據輸入的姓名查找聯系人的信息節點

      Input: 要輸入的電話列表list,姓名name

      Return: 返回查找到的節點

      */

      List FindPersonByName(List list,char* name)

      {

      while(list!=NULL)

      {

      if(strcmp(list->name,name)==0)

      break;

      list=list->next;

      }

      return list;

      }

      /*

      Function:根據姓名添加新的聯系人到聯系人列表

      Input: 指向聯系人列表地址的指針, 新用戶節點

      Return: 添加成功返回1,添加失敗返回0

      */

      int AddPersonByName(PList list,List node)

      {

      if(node==NULL)

      {

      printf("the node is NULL! ");

      return 0;

      }

      if(*list==NULL)

      {

      *list=node;

      return 1;

      }

      List pHead=*list;

      while(pHead->next!=NULL)

      pHead=pHead->next;

      pHead->next=node;

      return 1;

      }

      void AddPerson(PList list)

      {

      Position tmp;

      Position p_head;

      tmp=(struct node*)malloc(sizeof(struct node));

      char name[N];

      char number[M];

      if(tmp==NULL)

      {

      printf("malloc the tmp node failed in function add person! ");

      }

      else

      {

      printf("please input the name: ");

      gets(name);

      printf("please input the number: ");

      gets(number);

      strcpy(tmp->name,name);

      strcpy(tmp->number,number);

      tmp->next=NULL;

      }

      if(JudgeNameExist(*list,name)==1)

      {

      free(tmp);

      printf("the name have already exist! ");

      return;

      }

      AddPersonByName(list,tmp);

      }

      /*

      Function: 打印聯系人列表

      Input: 聯系人列表

      */

      void PrintList(List list)

      {

      Position show;

      show=list;

      if(show==NULL)

      {

      return ;

      }

      printf("Now,we print the phone list: ");

      while(show!=NULL)

      {

      printf("Name:%s Number:%s ",show->name,show->number);

      show=show->next;

      }

      }

      List FindPerson(List list)

      {

      char name[N];

      Position pHead=list;

      printf("please input the name you will find: ");

      gets(name);

      Position node=FindPersonByName(list,name);

      if(node!=NULL)

      printf("find success! name-> %s number-> %s ",node->name,node->number);

      else

      printf("find failed! ");

      return node;

      }

      /*

      Function:根據姓名刪除聯系人

      Input: 指向聯系人地址的指針,聯系人姓名

      Output: 刪除成功返回1,失敗返回0

      */

      int DeletePersonByName(PList list,char* name)

      {

      if(*list==NULL||name==NULL)

      return 0;

      List pHead=*list;

      if(strcmp(pHead->name,name)==0)

      {

      *list=pHead->next;

      free(pHead);

      pHead->next==NULL;

      return 0;

      }

      List tmp=pHead->next;

      while(tmp!=NULL)

      {

      if(strcmp(tmp->name,name)==0)

      {

      pHead->next=tmp->next;

      free(tmp);

      tmp->next=NULL;

      return 1;

      }

      pHead=tmp;

      tmp=tmp->next;

      }

      return 0;

      }

      void DeletePerson(PList list)

      {

      List pHead=*list;

      if(pHead==NULL)

      {

      printf("there is no person you can delet ");

      return ;

      }

      char name[N];

      printf("please input the name: ");

      gets(name);

      DeletePersonByName(list,name);

      }

    【c語言鏈表的用法】相關文章:

    c語言鏈表的用法有哪些09-07

    鏈表的C語言實現方法08-27

    C語言鏈表逆序方法技巧08-21

    C語言的循環鏈表和約瑟夫環09-29

    鏈表的C語言實現方法編程學習06-12

    c語言strcmp的用法10-26

    c語言if語句的用法07-23

    assert用法(C語言)05-30

    C語言#include用法10-17

    <address id="ousso"></address>
    <form id="ousso"><track id="ousso"><big id="ousso"></big></track></form>
    1. 日日做夜狠狠爱欧美黑人