商務英語計算機英語

c語言鏈表的用法

本文已影響 2.04W人 
ing-bottom: 100%;">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!n");  return NULL;  }  else  {  p=tmp;  printf("please input the first node's message!n");  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",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!n");  return NULL;  }  else  {  printf("please input the delete Node's value:n");  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    Data:2015/07/27  **************************************************************************/  #include<stdio.h>  #include<string.h>  #include<stdlib.h>  #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 n");  printf(" ******* 1 add a person *******n");  printf(" ******* 2 show the phone list *******n");  printf(" ******* 3 find from phone list *******n");  printf(" ******* 4 delete from phone list *******nnn");  printf("Please input the cmd number:n");  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!n");  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!n");  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!n");  }  else  {  printf("please input the name:n");  gets(name);  printf("please input the number:n");  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!n");  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:n");  while(show!=NULL)  {  printf("Name:%s Number:%sn",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:n");  gets(name);  Position node=FindPersonByName(list,name);  if(node!=NULL)  printf("find success! name-> %s number-> %sn",node->name,node->number);  else  printf("find failed!n");  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 deletn");  return ;  }  char name[N];  printf("please input the name:n");  gets(name);  DeletePersonByName(list,name);  }

猜你喜歡

熱點閱讀

最新文章