環球熱推薦:常用數據結構:單向鏈表和雙向鏈表的實現

2022-12-19 18:11:42 來源:51CTO博客

1、鏈表是什么?

鏈表是編程語言中常見的一種數據結構,它可以實現動態的創建和刪除,只要內存足夠,鏈表的數量和長度是可以無限多和無限長的。

鏈表顧名思義是一種鏈式的數據結構,它由一個個節點組成,并通過節點之間的互相關聯鏈接,形成了類似一條鏈式的結構。


(資料圖片僅供參考)

鏈表的節點一般可以分為數據域和指針域。數據域中是存放節點數據的,往往鏈表的節點都是結構體類型的,可以方便定義多種不同的數據類型,便于使用。指針域是存放節點的指針的,是鏈表中每個節點能互相串聯起來的關鍵,這個至關重要!

一個鏈表節點的示意圖如下:

2、單向鏈表

2.1、單向不循環鏈表

單向不循環鏈表是一種單向的鏈式結構,節點之間通過指針域互相關聯,最后一個節點的指針域為空(NULL)。如下圖所示:

下面用C語言實現一個單向不循環鏈表的代碼。

(1) 先定義一個鏈表的節點。如下:

// 定義一個鏈表節點的數據域。以記錄一個蘋果的信息為例,為方便說明,假設每個蘋果的信息各不相同typedef struct LinkData_struct{  int  weight; // 蘋果的重量  int  hight;  // 蘋果的高度  // ...     // 還可以定義更多的其他的數據}LinkData_t;/*** 定義一個鏈表節點 ******/typedef struct LinkNode_Struct{  LinkData_t data;        // 鏈表節點的數據域  struct LinkNode_Struct *Next;   // 鏈表節點的指針域}LinkNode_t;

(2) 定義一個單向鏈表的頭結點。如下:

/*** 定義一個單向鏈表的頭結點 ***/LinkNode_t AppleInfo_head; //作為單向鏈表的一個頭結點

(3) 初始化單向鏈表。如下:

// 初始化單向鏈表的頭結點void Init_LinkNode(LinkNode_t * HeadNode){  HeadNode->Next = NULL;}

(4) 創建鏈表節點并接入到鏈表中。如下:

// 創建一個鏈表節點并接入到鏈表中LinkNode_t * LinkNode_Create(LinkNode_t * HeadNode, LinkData_t *InsetData){  LinkNode_t *Node,*pf;  LinkNode_t *xReturn = NULL;  Node = (LinkNode_t *)malloc(sizeof(LinkNode_t));  if (Node == NULL)  {    printf("節點創建失敗!!!\r\n");    return NULL;  }  pf = HeadNode;  while(pf->Next != NULL)  {    pf = pf->Next;  }  pf->Next = Node;  Node->Next = NULL;  Node->data.hight = InsetData->hight;  Node->data.weight = InsetData->weight;  xReturn = Node;  printf("完成一個鏈表節點的創建,地址 = 0x%X\r\n",xReturn);  return xReturn;}

(5) 刪除鏈表中的節點。如下:

// 刪除鏈表中的某個節點,根據weight進行刪除void destroy_LinkNode(LinkNode_t * HeadNode, int weight){  int deleteFlag = 0;  LinkNode_t *pf,*preStre;  pf = preStre = HeadNode;  do  {    if (pf->data.weight == weight){      deleteFlag = 1;      break;    }    preStre = pf;    pf = pf->Next;  }while (pf->Next != NULL);  if (!deleteFlag)  {    printf("找不到這個節點!!!\r\n");  }  else  {    if(pf->Next == NULL) // 該點是尾節點    {      preStre->Next = NULL;    }    else    {      preStre->Next = pf->Next;    }    free(pf);    printf("節點weight = %d 銷毀成功!\r\n",weight);  }}

(6) 輸出整條鏈表的數據。如下:

// 輸出顯示整條鏈表void print_LinkNode_Info(LinkNode_t * HeadNode){  int length = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    printf("weight = %d\r\n", (int)pf->data.weight);    printf("height = %d\r\n", (int)pf->data.hight);    printf("\r\n");    length++;  }while (pf->Next != NULL);  printf("鏈表輸出完成。長度為:%d\r\n",length);}

(7) 按條件查詢鏈表中某個節點的數據。如下:

// 按條件查詢鏈表中某個節點的數據void search_LinkNode_Info(LinkNode_t * HeadNode, int weight){  int length = 0;  char search_flag = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    if(pf->data.weight == weight)    {      search_flag = 1;      printf("weight = %d\r\n", (int)pf->data.weight);      printf("height = %d\r\n", (int)pf->data.hight);      printf("\r\n");    }    length++;  }while (pf->Next != NULL);  if(search_flag)  {    printf("鏈表查找結束。所在節點位置為:%d\r\n",length);  }  else  {    printf("整個鏈表中無滿足此條件的節點!\r\n");  }}

完整的demo如下:

注意:這個demo可以直接運行在控制臺上輸出顯示!

void print_debug_info(void){  printf("******** 鏈表控制臺 *****************\r\n");  printf("*                                  \r\n");  printf("*  1:創建鏈表                      \r\n");  printf("*  2:刪除鏈表                      \r\n");  printf("*  3:顯示整條鏈表的數據             \r\n");  printf("*  4:按條件查找鏈表節點             \r\n");  printf("*  8:清空顯示                      \r\n");  printf("*  9:結束運行                      \r\n");  printf("*                                  \r\n");  printf("************************************\r\n");}int main(int argc, char *argv[]) {  int Num,i,j;  int Options;  int weight,height;  LinkData_t InsetData;  Init_LinkNode(&AppleInfo_head);  while (1)  {    print_debug_info();    printf("\r\n請輸入需要操作的鍵值,按回車鍵確認!\r\n");    scanf("%d", &Options);    switch (Options)    {      case 1:        /*** 創建任意長度的鏈表 **********************************************************/        printf("請輸入需要創建的鏈表節點的數量,按回車結束!\r\n");        scanf("%d", &Num);        printf("請輸入節點的數據:\r\n");        for (i = 0; i < Num; i++)        {          printf("請輸入第 %d 節點的數據,weight = Height = ,輸入完畢按回車結束!\r\n",i+1);          scanf("%d %d", &weight,&height);          InsetData.weight = weight;          InsetData.hight  = height;          printf("weight = %d height = %d\r\n",weight,height);          if(LinkNode_Create(&AppleInfo_head, &InsetData) > NULL)          {            printf("節點 %d 創建成功!\r\n\r\n\r\n",i+1);          }          else          {            printf("節點 %d 創建失敗!\r\n\r\n\r\n",i+1);          }        }        printf("\r\n");        break;            case 2:        /******* 刪除鏈表中的某個節點 ***************************************************/        printf("請輸入需要刪除的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        destroy_LinkNode(&AppleInfo_head, Num);        printf("\r\n");        break;      case 3:        printf("鏈表數據為:\r\n");        print_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 4:        printf("請輸入需要查找的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        search_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 8:        system("cls");        break;      case 9:        printf("退出鏈表控制臺,請再次運行程序!\r\n");        return;        break;            default:        printf("無效的鍵值,請重新輸入!\r\n");        break;    }  }  return 0;}

2.2、單向循環鏈表

單向循環鏈表是一種單向的可回頭的鏈表,節點之間通過指針域互相關聯,最后一個節點的指針域為頭結點的地址。如下圖所示:

下面用C語言實現一個單向循環鏈表的代碼。

(1)先定義一個鏈表的節點。如下:

// 定義一個鏈表節點的數據域。以記錄一個蘋果的信息為例,為方便說明,假設每個蘋果的信息各不相同typedef struct LinkData_struct{  int  weight; // 蘋果的重量  int  hight;  // 蘋果的高度  // ...     // 還可以定義更多的其他的數據}LinkData_t;/*** 定義一個鏈表節點 ******/typedef struct LinkNode_Struct{  LinkData_t data;        // 鏈表節點的數據域  struct LinkNode_Struct *Next;   // 鏈表節點的指針域}LinkNode_t;

(2)定義一個單向鏈表的頭結點。如下:

/*** 定義一個單向鏈表的頭結點 ***/LinkNode_t AppleInfo_head; //作為單向鏈表的一個頭結點

(3)初始化單向鏈表。如下:

// 初始化單向循環鏈表的頭結點void Init_LinkNode(LinkNode_t * HeadNode){  HeadNode->Next = HeadNode;}

(4)創建鏈表節點并接入到鏈表中。如下:

// 創建一個鏈表節點并接入到單向循環鏈表中LinkNode_t * LinkNode_Create(LinkNode_t * HeadNode, LinkData_t *InsetData){  LinkNode_t *Node,*pf;  LinkNode_t *xReturn = NULL;  Node = (LinkNode_t *)malloc(sizeof(LinkNode_t));  if (Node == NULL)  {    printf("節點創建失敗!!!\r\n");    return NULL;  }  pf = HeadNode;  while(pf->Next != HeadNode)  {    pf = pf->Next;  }  pf->Next = Node;  Node->Next = HeadNode;  Node->data.hight = InsetData->hight;  Node->data.weight = InsetData->weight;  xReturn = Node;  printf("完成一個鏈表節點的創建,地址 = 0x%X\r\n",xReturn);  return xReturn;}

(5)刪除鏈表中的節點。如下:

// 刪除鏈表中的某個節點,根據weight進行刪除void destroy_LinkNode(LinkNode_t * HeadNode, int weight){  int deleteFlag = 0;  LinkNode_t *pf,*preStre;  pf = preStre = HeadNode;  do  {    preStre = pf;    pf = pf->Next;    if (pf->data.weight == weight){      deleteFlag = 1;      break;    }  }while (pf->Next != HeadNode);  if (!deleteFlag)  {    printf("找不到這個節點!!!\r\n");  }  else  {    if(pf->Next == HeadNode) // 該點是尾節點    {      preStre->Next = HeadNode;    }    else    {      preStre->Next = pf->Next;    }    free(pf);    printf("節點weight = %d 銷毀成功!\r\n",weight);  }}

(6)輸出整條鏈表的數據。如下:

// 輸出顯示整條鏈表void print_LinkNode_Info(LinkNode_t * HeadNode){  int length = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == HeadNode)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    printf("weight = %d\r\n", (int)pf->data.weight);    printf("height = %d\r\n", (int)pf->data.hight);    printf("\r\n");    length++;  }while (pf->Next != HeadNode);  printf("鏈表輸出完成。長度為:%d\r\n",length);}

(7)按條件查詢鏈表中某個節點的數據。如下:

// 按條件查詢鏈表中某個節點的數據void search_LinkNode_Info(LinkNode_t * HeadNode, int weight){  int length = 0;  char search_flag = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == HeadNode)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    if(pf->data.weight == weight)    {      search_flag = 1;      printf("weight = %d\r\n", (int)pf->data.weight);      printf("height = %d\r\n", (int)pf->data.hight);      printf("\r\n");    }    length++;  }while (pf->Next != HeadNode);  if(search_flag)  {    printf("鏈表查找結束。所在節點位置為:%d\r\n",length);  }  else  {    printf("整個鏈表中無滿足此條件的節點!\r\n");  }}

完整的demo如下:

注意:這個demo可以直接運行在控制臺上輸出顯示!

void print_debug_info(void){  printf("******** 鏈表控制臺 *****************\r\n");  printf("*                                  \r\n");  printf("*  1:創建鏈表                      \r\n");  printf("*  2:刪除鏈表                      \r\n");  printf("*  3:顯示整條鏈表的數據             \r\n");  printf("*  4:按條件查找鏈表節點             \r\n");  printf("*  8:清空顯示                      \r\n");  printf("*  9:結束運行                      \r\n");  printf("*                                  \r\n");  printf("************************************\r\n");}int main(int argc, char *argv[]) {  int Num,i,j;  int Options;  int weight,height;  LinkData_t InsetData;  Init_LinkNode(&AppleInfo_head);  while (1)  {    print_debug_info();    printf("\r\n請輸入需要操作的鍵值,按回車鍵確認!\r\n");    scanf("%d", &Options);    switch (Options)    {      case 1:        /*** 創建任意長度的鏈表 **********************************************************/        printf("請輸入需要創建的鏈表節點的數量,按回車結束!\r\n");        scanf("%d", &Num);        printf("請輸入節點的數據:\r\n");        for (i = 0; i < Num; i++)        {          printf("請輸入第 %d 節點的數據,weight = Height = ,輸入完畢按回車結束!\r\n",i+1);          scanf("%d %d", &weight,&height);          InsetData.weight = weight;          InsetData.hight  = height;          printf("weight = %d height = %d\r\n",weight,height);          if(LinkNode_Create(&AppleInfo_head, &InsetData) > NULL)          {            printf("節點 %d 創建成功!\r\n\r\n\r\n",i+1);          }          else          {            printf("節點 %d 創建失敗!\r\n\r\n\r\n",i+1);          }        }        printf("\r\n");        break;            case 2:        /******* 刪除鏈表中的某個節點 ***************************************************/        printf("請輸入需要刪除的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        destroy_LinkNode(&AppleInfo_head, Num);        printf("\r\n");        break;      case 3:        printf("鏈表數據為:\r\n");        print_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 4:        printf("請輸入需要查找的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        search_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 8:        system("cls");        break;      case 9:        printf("退出鏈表控制臺,請再次運行程序!\r\n");        return;        break;            default:        printf("無效的鍵值,請重新輸入!\r\n");        break;    }  }  return 0;}

3、雙向鏈表

雙向鏈表和單向鏈表相比,最大的不同是指針域中多了一個指向前一個節點的地址域。這樣一來,雙向鏈表中的每個節點就保存了前后節點的地址,從而通過地址形成一條鏈式的存儲結構。

雙向鏈表的最大便利之處在于查詢鏈表時不僅可以正向查找也可以反向查找,甚至如果當前查詢的位置在鏈表中間的位置的時候,可以反方向兩頭查找,提高查找的速度和效率,增加了便利。

雙向鏈表也有循環和不循環兩種方式,下面分別介紹。

3.1、雙向不循環鏈表

雙向不循環鏈表是頭結點的前一個指針指向頭結點自身,尾節點的后一個指針指向為NULL。示意圖如下:

雙向不循環鏈表的代碼實現如下示例:

#include #include /*** 定義鏈表操作的位置:開頭、中間、結尾 ***/typedef enum{  Head = 1,  Middle,  End,}Location;/*** 定義一個鏈表節點 ******/// 1.定義一個鏈表節點的數據域。以記錄一個蘋果的信息為例,為方便說明,假設每個蘋果的信息各不相同typedef struct LinkData_struct{  int  weight; // 蘋果的重量  int  hight;  // 蘋果的高度  // ...     // 還可以定義更多的其他的數據}LinkData_t;typedef struct LinkNode_Struct{  LinkData_t data;        // 鏈表節點的數據域  struct LinkNode_Struct *Prev;   // 鏈表節點的上一個節點的指針域  struct LinkNode_Struct *Next;   // 鏈表節點的下一個節點的指針域}LinkNode_t;/*** 定義一個單向鏈表的頭結點 ***/LinkNode_t AppleInfo_head; //作為單向鏈表的一個頭結點// 初始化單向鏈表的頭結點void Init_LinkNode(LinkNode_t * HeadNode){  HeadNode->Next = NULL;  HeadNode->Prev = NULL;}// 創建一個鏈表節點并接入到鏈表中LinkNode_t * LinkNode_Create(LinkNode_t * HeadNode, LinkData_t *InsetData){  LinkNode_t *Prev_pf,*Next_pf;  LinkNode_t *xReturn = NULL;  LinkNode_t *Node = (LinkNode_t *)malloc(sizeof(LinkNode_t));  if (Node == NULL)  {    printf("節點創建失敗!!!\r\n");    return NULL;  }  Prev_pf = Next_pf = HeadNode;    // 第一節點從頭結點后面開始插入  if (HeadNode->Next == NULL && HeadNode->Prev == NULL)  {    HeadNode->Next = Node;    Node->Next = NULL;    Node->Prev = HeadNode;    Node->data.hight  = InsetData->hight;    Node->data.weight = InsetData->weight;    xReturn = Node;  }  else  {    while (Next_pf->Next != NULL)    {      Next_pf = Next_pf->Next;    }    Next_pf->Next = Node;    Node->Prev = Next_pf;    Node->Next = NULL;    Node->data.hight = InsetData->hight;    Node->data.weight = InsetData->weight;    xReturn = Node;  }    printf("完成一個鏈表節點的創建,地址 = 0x%X\r\n",xReturn);  return xReturn;}// 刪除鏈表中的某個節點,根據weight進行刪除void destroy_LinkNode(LinkNode_t * HeadNode, int weight){  int deleteFlag = 0;  LinkNode_t *pf;  pf = HeadNode;  do  {    pf = pf->Next;    if (pf->data.weight == weight)    {      deleteFlag = 1;      break;    }     }while (pf->Next != NULL);  if (!deleteFlag)  {    printf("鏈表中找不到這個節點!!!\r\n");  }  else  {    if (pf->Next == NULL)    {      pf->Prev->Next = NULL;    }    else    {      pf->Prev->Next = pf->Next;      pf->Next->Prev = pf->Prev;     }        free(pf);    printf("節點weight = %d 銷毀成功!\r\n",weight);  }}// 輸出顯示整條鏈表void print_LinkNode_Info(LinkNode_t * HeadNode){  int length = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    printf("weight = %d\r\n", (int)pf->data.weight);    printf("height = %d\r\n", (int)pf->data.hight);    printf("\r\n");    length++;  }while (pf->Next != NULL);  printf("鏈表輸出完成。長度為:%d\r\n",length);}// 按條件查詢鏈表中某個節點的數據void search_LinkNode_Info(LinkNode_t * HeadNode, int weight){  int length = 0;  char search_flag = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    if(pf->data.weight == weight)    {      search_flag = 1;      printf("weight = %d\r\n", (int)pf->data.weight);      printf("height = %d\r\n", (int)pf->data.hight);      printf("\r\n");    }    length++;  }while (pf->Next != NULL);  if(search_flag)  {    printf("鏈表查找結束。所在節點位置為:%d\r\n",length);  }  else  {    printf("整個鏈表中無滿足此條件的節點!\r\n");  }}// 查詢鏈表中有幾個相同的數據void search_Same_LinkNode_Info(LinkNode_t * HeadNode, int weight){  int length = 0,cnt = 0;  char search_flag = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    length++;    if(pf->data.weight == weight)    {      search_flag = 1;      printf("weight = %d\r\n", (int)pf->data.weight);      printf("height = %d\r\n", (int)pf->data.hight);      printf("這個節點在鏈表中的位置:%d\r\n",length);      cnt++;    }  }while (pf->Next != NULL);  if(search_flag)  {    printf("鏈表查找結束。相同數據的節點數量為:%d\r\n",cnt);  }  else  {    printf("整個鏈表中無滿足此條件的節點!\r\n");  }}void print_debug_info(void){  printf("******** 鏈表控制臺 *****************\r\n");  printf("*                                  \r\n");  printf("*  1:創建鏈表                      \r\n");  printf("*  2:刪除鏈表                      \r\n");  printf("*  3:顯示整條鏈表的數據             \r\n");  printf("*  4:按條件查找鏈表節點             \r\n");  printf("*  5:查找鏈表中有幾個相同數據的節點  \r\n");  printf("*  8:清空顯示                      \r\n");  printf("*  9:結束運行                      \r\n");  printf("*                                  \r\n");  printf("************************************\r\n");}int main(int argc, char *argv[]) {  int Num,i,j;  int Options;  int weight,height;  LinkData_t InsetData;  Init_LinkNode(&AppleInfo_head);    while (1)  {    print_debug_info();    printf("\r\n請輸入需要操作的鍵值,按回車鍵確認!\r\n");    scanf("%d", &Options);    switch (Options)    {      case 1:        /*** 創建任意長度的鏈表 **********************************************************/        printf("請輸入需要創建的鏈表節點的數量,按回車結束!\r\n");        scanf("%d", &Num);        printf("請輸入節點的數據:\r\n");        for (i = 0; i < Num; i++)        {          printf("請輸入第 %d 節點的數據,weight = Height = ,輸入完畢按回車結束!\r\n",i+1);          scanf("%d %d", &weight,&height);          InsetData.weight = weight;          InsetData.hight  = height;          printf("weight = %d height = %d\r\n",weight,height);          if(LinkNode_Create(&AppleInfo_head, &InsetData) > NULL)          {            printf("節點 %d 創建成功!\r\n\r\n\r\n",i+1);          }          else          {            printf("節點 %d 創建失敗!\r\n\r\n\r\n",i+1);          }        }        printf("\r\n");        break;            case 2:        /******* 刪除鏈表中的某個節點 ***************************************************/        printf("請輸入需要刪除的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        destroy_LinkNode(&AppleInfo_head, Num);        printf("\r\n");        break;      case 3:        printf("鏈表數據為:\r\n");        print_LinkNode_Info(&AppleInfo_head);        printf("\r\n");        break;      case 4:        printf("請輸入需要查找的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        search_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 5:        printf("請輸入需要查找的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        search_Same_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 8:        system("cls");        break;      case 9:        printf("退出鏈表控制臺,請再次運行程序!\r\n");        return;        break;            default:        printf("無效的鍵值,請重新輸入!\r\n");        break;    }  }  return 0;}

3.2、雙向循環鏈表

雙向循環鏈表是頭結點的前一個指針指向尾結點的地址,尾節點的后一個指針指向頭結點的地址所在,從而構成一種鏈式的循環結構。示意圖如下:

雙向循環鏈表的示意代碼如下:

#include #include /*** 定義鏈表操作的位置:開頭、中間、結尾 ***/typedef enum{  Head = 1,  Middle,  End,}Location;/*** 定義一個鏈表節點 ******/// 1.定義一個鏈表節點的數據域。以記錄一個蘋果的信息為例,為方便說明,假設每個蘋果的信息各不相同typedef struct LinkData_struct{  int  weight; // 蘋果的重量  int  hight;  // 蘋果的高度  // ...     // 還可以定義更多的其他的數據}LinkData_t;typedef struct LinkNode_Struct{  LinkData_t data;        // 鏈表節點的數據域  struct LinkNode_Struct *Prev;   // 鏈表節點的上一個節點的指針域  struct LinkNode_Struct *Next;   // 鏈表節點的下一個節點的指針域}LinkNode_t;/*** 定義一個單向鏈表的頭結點 ***/LinkNode_t AppleInfo_head; //作為單向鏈表的一個頭結點// 初始化單向鏈表的頭結點void Init_LinkNode(LinkNode_t * HeadNode){  HeadNode->Next = NULL;  HeadNode->Prev = HeadNode; // 雙向循環鏈表的頭結點的前一個指針指向頭結點本身}// 創建一個鏈表節點并接入到鏈表中LinkNode_t * LinkNode_Create(LinkNode_t * HeadNode, LinkData_t *InsetData){  LinkNode_t *Prev_pf,*Next_pf;  LinkNode_t *xReturn = NULL;  LinkNode_t *Node = (LinkNode_t *)malloc(sizeof(LinkNode_t));  if (Node == NULL)  {    printf("節點創建失敗!!!\r\n");    return NULL;  }  Prev_pf = Next_pf = HeadNode;    // 第一節點從頭結點后面開始插入  if (HeadNode->Next == NULL && HeadNode->Prev == HeadNode)  {    HeadNode->Next = Node;    HeadNode->Prev = Node;    Node->Next = HeadNode;    Node->Prev = HeadNode;    Node->data.hight  = InsetData->hight;    Node->data.weight = InsetData->weight;    xReturn = Node;  }  else  {    while (Next_pf->Next != HeadNode)    {      Next_pf = Next_pf->Next;    }    Next_pf->Next  = Node;    HeadNode->Prev = Node;    Node->Prev = Next_pf;    Node->Next = HeadNode;    Node->data.hight = InsetData->hight;    Node->data.weight = InsetData->weight;    xReturn = Node;  }    printf("完成一個鏈表節點的創建,地址 = 0x%X\r\n",xReturn);  return xReturn;}// 刪除鏈表中的某個節點,根據weight進行刪除void destroy_LinkNode(LinkNode_t * HeadNode, int weight){  int deleteFlag = 0;  LinkNode_t *pf;  pf = HeadNode;  do  {    pf = pf->Next;    if (pf->data.weight == weight)    {      deleteFlag = 1;      break;    }     }while (pf->Next != HeadNode);  if (!deleteFlag)  {    printf("鏈表中找不到這個節點!!!\r\n");  }  else  {    if (pf->Next == HeadNode)    {      pf->Prev->Next = HeadNode;      HeadNode->Prev = pf;    }    else    {      pf->Prev->Next = pf->Next;      pf->Next->Prev = pf->Prev;     }        free(pf);    printf("節點weight = %d 銷毀成功!\r\n",weight);  }}// 輸出顯示整條鏈表void print_LinkNode_Info(LinkNode_t * HeadNode){  int length = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    printf("weight = %d\r\n", (int)pf->data.weight);    printf("height = %d\r\n", (int)pf->data.hight);    printf("\r\n");    length++;  }while (pf->Next != HeadNode);  printf("鏈表輸出完成。長度為:%d\r\n",length);}// 按條件查詢鏈表中某個節點的數據void search_LinkNode_Info(LinkNode_t * HeadNode, int weight){  int length = 0;  char search_flag = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    if(pf->data.weight == weight)    {      search_flag = 1;      printf("weight = %d\r\n", (int)pf->data.weight);      printf("height = %d\r\n", (int)pf->data.hight);      printf("\r\n");    }    length++;  }while (pf->Next != HeadNode);  if(search_flag)  {    printf("鏈表查找結束。所在節點位置為:%d\r\n",length);  }  else  {    printf("整個鏈表中無滿足此條件的節點!\r\n");  }}// 查詢鏈表中有幾個相同的數據void search_Same_LinkNode_Info(LinkNode_t * HeadNode, int weight){  int length = 0,cnt = 0;  char search_flag = 0;  LinkNode_t *pf = HeadNode;  if (pf->Next == NULL)  {    printf("該鏈表長度為零,不能輸出結果!\r\n");    return;  }  do    {    pf = pf->Next;    length++;    if(pf->data.weight == weight)    {      search_flag = 1;      printf("weight = %d\r\n", (int)pf->data.weight);      printf("height = %d\r\n", (int)pf->data.hight);      printf("這個節點在鏈表中的位置:%d\r\n",length);      cnt++;    }  }while (pf->Next != HeadNode);  if(search_flag)  {    printf("鏈表查找結束。相同數據的節點數量為:%d\r\n",cnt);  }  else  {    printf("整個鏈表中無滿足此條件的節點!\r\n");  }}void print_debug_info(void){  printf("******** 鏈表控制臺 *****************\r\n");  printf("*                                  \r\n");  printf("*  1:創建鏈表                      \r\n");  printf("*  2:刪除鏈表                      \r\n");  printf("*  3:顯示整條鏈表的數據             \r\n");  printf("*  4:按條件查找鏈表節點             \r\n");  printf("*  5:查找鏈表中有幾個相同數據的節點  \r\n");  printf("*  8:清空顯示                      \r\n");  printf("*  9:結束運行                      \r\n");  printf("*                                  \r\n");  printf("************************************\r\n");}int main(int argc, char *argv[]) {  int Num,i,j;  int Options;  int weight,height;  LinkData_t InsetData;  Init_LinkNode(&AppleInfo_head);    while (1)  {    print_debug_info();    printf("\r\n請輸入需要操作的鍵值,按回車鍵確認!\r\n");    scanf("%d", &Options);    switch (Options)    {      case 1:        /*** 創建任意長度的鏈表 **********************************************************/        printf("請輸入需要創建的鏈表節點的數量,按回車結束!\r\n");        scanf("%d", &Num);        printf("請輸入節點的數據:\r\n");        for (i = 0; i < Num; i++)        {          printf("請輸入第 %d 節點的數據,weight = Height = ,輸入完畢按回車結束!\r\n",i+1);          scanf("%d %d", &weight,&height);          InsetData.weight = weight;          InsetData.hight  = height;          printf("weight = %d height = %d\r\n",weight,height);          if(LinkNode_Create(&AppleInfo_head, &InsetData) > NULL)          {            printf("節點 %d 創建成功!\r\n\r\n\r\n",i+1);          }          else          {            printf("節點 %d 創建失敗!\r\n\r\n\r\n",i+1);          }        }        printf("\r\n");        break;            case 2:        /******* 刪除鏈表中的某個節點 ***************************************************/        printf("請輸入需要刪除的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        destroy_LinkNode(&AppleInfo_head, Num);        printf("\r\n");        break;      case 3:        printf("鏈表數據為:\r\n");        print_LinkNode_Info(&AppleInfo_head);        printf("\r\n");        break;      case 4:        printf("請輸入需要查找的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        search_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 5:        printf("請輸入需要查找的鏈表節點的weight,按回車結束!\r\n");        scanf("%d", &Num);        search_Same_LinkNode_Info(&AppleInfo_head, Num);        printf("\r\n");        break;      case 8:        system("cls");        break;      case 9:        printf("退出鏈表控制臺,請再次運行程序!\r\n");        return;        break;            default:        printf("無效的鍵值,請重新輸入!\r\n");        break;    }  }  return 0;}

標簽: 鏈表節點 循環鏈表 創建鏈表

上一篇:焦點報道:Spring Shell Reference Documentation(參考文檔)
下一篇:GO語言入門第五節 Go語言的并發編程