婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > JavaScript實現鏈表插入排序和鏈表歸并排序

JavaScript實現鏈表插入排序和鏈表歸并排序

熱門標簽:泰州泰興400電話 怎么申請 南京新思維電話機器人 地圖標注市場怎么樣 企業怎么在聯通申請400電話 好操作的電話機器人廠家 聊城智能電銷機器人外呼 南昌市地圖標注app 如何用中國地圖標注數字點 百度地圖添加標注圖標樣式

本篇文章詳細的介紹了JavaScript實現鏈表插入排序和鏈表歸并排序,鏈表的歸并排序就是對每個部分都進行歸并排序,然后合并在一起。

1.鏈表

1.1鏈表的存儲表示

//鏈表的存儲表示
typedef int ElemType;
typedef struct LNode
{
  ElemType data;
  struct LNode *next;
}LNode, *LinkList;

1.2基本操作

創建鏈表:

/*
 * 創建鏈表。
 * 形參num為鏈表的長度,函數返回鏈表的頭指針。
 */
LinkList CreatLink(int num)
{
  int i, data;
 
  //p指向當前鏈表中最后一個結點,q指向準備插入的結點。
  LinkList head = NULL, p = NULL, q;
 
  for (i = 0; i  num; i++)
  {
    scanf("%d", data);
    q = (LinkList)malloc(sizeof(LNode));
    q->data = data;
    q->next = NULL;
    if (i == 0)
    {
      head = q;
    }
    else
    {
      p->next = q;
    }
    p = q;
  }
  return head;
}

輸出鏈表:

/*
 * 輸出鏈表結點值。
 */
int PrintLink(LinkList head)
{
  LinkList p;
  for (p = head; p ;p = p->next)
  {
    printf("%-3d ", p->data);
  }
  return 0;
}

2.鏈表插入排序

基本思想:假設前面n-1個結點有序,將第n個結點插入到前面結點的適當位置,使這n個結點有序。

實現方法:

將鏈表上第一個結點拆下來,成為含有一個結點的鏈表(head1),其余的結點自然成為另外一個鏈表(head2),此時head1為含有

一個結點的有序鏈表;

將鏈表head2上第一個結點拆下來,插入到鏈表head1的適當位置,使head1仍有序,此時head1成為含有兩個結點的有序鏈表;

依次從鏈表head2上拆下一個結點,插入到鏈表head1中,直到鏈表head2為空鏈表為止。最后,鏈表head1上含所有結點,且結點有序。

插入排序代碼:

/*
 * 鏈表插入排序(由小到大)。
 * 輸入:鏈表的頭指針,
 * 輸出:排序后鏈表的頭指針。
 * 實現方法:將原鏈表拆成兩部分:鏈表1仍以head為頭指針,鏈表結點有序。鏈表2以head2為頭指針,鏈表結點無序。
 * 將鏈表2中的結點依次插入到鏈表1中,并保持鏈表1有序。
 * 最后鏈表1中包含所有結點,且有序。
 */
LinkList LinkInsertSort(LinkList head)
{
  //current指向當前待插入的結點。
  LinkList head2, current, p, q;
 
  if (head == NULL)
    return head;
 
  //第一次拆分。
  head2 = head->next;
  head->next = NULL;
 
  while (head2)
  {
    current = head2;
    head2 = head2->next;
 
    //尋找插入位置,插入位置為結點p和q中間。
    for (p = NULL, q = head; q  q->data = current->data; p = q, q = q->next);
 
    if (q == head)
    {
      //將current插入最前面。
      head = current;
    }
    else
    {
      p->next = current;
    }
    current->next = q;
  }
  return head;
}

完整源代碼:

/*
 * 鏈表插入排序,由小到大
 */
#define _CRT_SECURE_NO_WARNINGS
#include stdio.h>
#include stdlib.h>

#define TOTAL 10    //鏈表長度

//鏈表的存儲表示
typedef int ElemType;
typedef struct LNode
{
  ElemType data;
  struct LNode *next;
}LNode, *LinkList;

LinkList CreatLink(int num);
LinkList LinkInsertSort(LinkList head);
int PrintLink(LinkList head);

/*
 * 創建鏈表。
 * 形參num為鏈表的長度,函數返回鏈表的頭指針。
 */
LinkList CreatLink(int num)
{
  int i, data;

  //p指向當前鏈表中最后一個結點,q指向準備插入的結點。
  LinkList head = NULL, p = NULL, q;

  for (i = 0; i  num; i++)
  {
    scanf("%d", data);
    q = (LinkList)malloc(sizeof(LNode));
    q->data = data;
    q->next = NULL;
    if (i == 0)
    {
      head = q;
    }
    else
    {
      p->next = q;
    }
    p = q;
  }
  return head;
}

/*
 * 鏈表插入排序(由小到大)。
 * 輸入:鏈表的頭指針,
 * 輸出:排序后鏈表的頭指針。
 * 實現方法:將原鏈表拆成兩部分:鏈表1仍以head為頭指針,鏈表結點有序。鏈表2以head2為頭指針,鏈表結點無序。
 * 將鏈表2中的結點依次插入到鏈表1中,并保持鏈表1有序。
 * 最后鏈表1中包含所有結點,且有序。
 */
LinkList LinkInsertSort(LinkList head)
{
  //current指向當前待插入的結點。
  LinkList head2, current, p, q;

  if (head == NULL)
    return head;

  //第一次拆分。
  head2 = head->next;
  head->next = NULL;

  while (head2)
  {
    current = head2;
    head2 = head2->next;

    //尋找插入位置,插入位置為結點p和q中間。
    for (p = NULL, q = head; q  q->data = current->data; p = q, q = q->next);

    if (q == head)
    {
      //將current插入最前面。
      head = current;
    }
    else
    {
      p->next = current;
    }
    current->next = q;
  }
  return head;
}

/*
 * 輸出鏈表結點值。
 */
int PrintLink(LinkList head)
{
  LinkList p;
  for (p = head; p ;p = p->next)
  {
    printf("%-3d ", p->data);
  }
  return 0;
}

int main()
{
  LinkList head;

  printf("輸入Total個數以創建鏈表:\n");
  head = CreatLink(TOTAL);
  
  head = LinkInsertSort(head);
  printf("排序后:\n");
  PrintLink(head);
  putchar('\n');
  return 0;
}

3.鏈表歸并排序

基本思想:如果鏈表為空或者含有一個結點,鏈表自然有序。否則,將鏈表分成兩部分,對每一部分分別進行歸并排序,然后將已排序的兩個鏈表歸并在一起。

歸并排序代碼:

/*
 * 鏈表歸并排序(由小到大)。
 * 輸入:鏈表的頭指針,
 * 輸出:排序后鏈表的頭指針。
 * 遞歸實現方法:將鏈表head分為兩部分,分別進行歸并排序,再將排序后的兩部分歸并在一起。
 * 遞歸結束條件:進行遞歸排序的鏈表為空或者只有一個結點。
 */
LinkList LinkMergeSort(LinkList head)
{
  LinkList head1, head2;
  if (head == NULL || head->next == NULL)
    return head;
 
  LinkSplit(head, head1, head2);
  head1 = LinkMergeSort(head1);
  head2 = LinkMergeSort(head2);
  head = LinkMerge(head1, head2);
  return head;
}

其中鏈表分割函數如下,基本思想是利用slow/fast指針,具體實現方法見注釋。

/*
 * 鏈表分割函數。
 * 將鏈表head均分為兩部分head1和head2,若鏈表長度為奇數,多出的結點從屬于第一部分。
 * 實現方法:首先使指針slow/fast指向鏈首,
 * 然后使fast指針向前移動兩個結點的同時,slow指針向前移動一個結點,
 * 循環移動,直至fast指針指向鏈尾。結束時,slow指向鏈表head1的鏈尾。
 */
int LinkSplit(LinkList head, LinkList *head1, LinkList *head2)
{
  LinkList slow, fast;
 
  if (head == NULL || head->next == NULL)
  {
    *head1 = head;
    *head2 = NULL;
    return 0;
  }
  slow = head;
  fast = head->next;
  while (fast)
  {
    fast = fast->next;
    if (fast)
    {
      fast = fast->next;
      slow = slow->next;
    }
  }
  *head1 = head;
  *head2 = slow->next;
 
  //注意:一定要將鏈表head1的鏈尾置空。
  slow->next = NULL;
  return 0;
}

鏈表歸并函數有遞歸實現和非遞歸實現兩種方法:

非遞歸實現:

/*
 * 鏈表歸并。
 * 將兩個有序的鏈表歸并在一起,使總鏈表有序。
 * 輸入:鏈表head1和鏈表head2
 * 輸出:歸并后的鏈表
 * 實現方法:將鏈表head2中的結點依次插入到鏈表head1中的適當位置,使head1仍為有序鏈表。
 */
LinkList LinkMerge(LinkList head1, LinkList head2)
{
  LinkList p, q, t;
 
  if (!head1)
    return head2;
  if (!head2)
    return head1;
 
  //循環變量的初始化,q指向鏈表head1中的當前結點,p為q的前驅。
  p = NULL;
  q = head1;
  while (head2)
  {
    //t為待插入結點。
    t = head2;
    head2 = head2->next;
    //尋找插入位置,插入位置為p和q之間。
    for (;q  q->data = t->data; p = q, q = q->next);
    if (p == NULL)
      head1 = t;
    else
      p->next = t;
    t->next = q;
    //將結點t插入到p和q之間后,使p重新指向q的前驅。
    p = t;
  }
  return head1;
}

遞歸實現:

LinkList LinkMerge2(LinkList head1, LinkList head2)
{
  LinkList result;
 
  if (!head1)
    return head2;
  if (!head2)
    return head1;
 
  if (head1->data = head2->data)
  {
    result = head1;
    result->next = LinkMerge(head1->next, head2);
  }
  else
  {
    result = head2;
    result->next = LinkMerge(head1, head2->next);
  }
  return result;
}

完整源代碼:

/*
* 鏈表歸并排序,由小到大。
*/
#define _CRT_SECURE_NO_WARNINGS
#include stdio.h>
#include stdlib.h>

#define TOTAL 10    //鏈表長度

//鏈表的存儲表示
typedef int ElemType;
typedef struct LNode
{
  ElemType data;
  struct LNode *next;
}LNode, *LinkList;

LinkList CreatLink(int num);
LinkList LinkMergeSort(LinkList head);
LinkList LinkMerge(LinkList head1, LinkList head2);
LinkList LinkMerge2(LinkList head1, LinkList head2);
int LinkSplit(LinkList head, LinkList *head1, LinkList *head2);
int PrintLink(LinkList head);

/*
* 創建鏈表。
* 形參num為鏈表的長度,函數返回鏈表的頭指針。
*/
LinkList CreatLink(int num)
{
  int i, data;

  //p指向當前鏈表中最后一個結點,q指向準備插入的結點。
  LinkList head = NULL, p = NULL, q;

  for (i = 0; i  num; i++)
  {
    scanf("%d", data);
    q = (LinkList)malloc(sizeof(LNode));
    q->data = data;
    q->next = NULL;
    if (i == 0)
    {
      head = q;
    }
    else
    {
      p->next = q;
    }
    p = q;
  }
  return head;
}

/*
* 輸出鏈表結點值。
*/
int PrintLink(LinkList head)
{
  LinkList p;
  for (p = head; p; p = p->next)
  {
    printf("%-3d ", p->data);
  }
  return 0;
}

int main()
{
  LinkList head;

  printf("輸入Total個數以創建鏈表:\n");
  head = CreatLink(TOTAL);

  head = LinkMergeSort(head);
  printf("排序后:\n");
  PrintLink(head);
  putchar('\n');
  return 0;
}

/*
 * 鏈表歸并排序(由小到大)。
 * 輸入:鏈表的頭指針,
 * 輸出:排序后鏈表的頭指針。
 * 遞歸實現方法:將鏈表head分為兩部分,分別進行歸并排序,再將排序后的兩部分歸并在一起。
 * 遞歸結束條件:進行遞歸排序的鏈表為空或者只有一個結點。
 */
LinkList LinkMergeSort(LinkList head)
{
  LinkList head1, head2;
  if (head == NULL || head->next == NULL)
    return head;

  LinkSplit(head, head1, head2);
  head1 = LinkMergeSort(head1);
  head2 = LinkMergeSort(head2);
  head = LinkMerge(head1, head2);    //非遞歸實現
  //head = LinkMerge2(head1, head2);  //遞歸實現
  return head;
}

/*
 * 鏈表歸并。
 * 將兩個有序的鏈表歸并在一起,使總鏈表有序。
 * 輸入:鏈表head1和鏈表head2
 * 輸出:歸并后的鏈表
 * 實現方法:將鏈表head2中的結點依次插入到鏈表head1中的適當位置,使head1仍為有序鏈表。
 */
LinkList LinkMerge(LinkList head1, LinkList head2)
{
  LinkList p, q, t;

  if (!head1)
    return head2;
  if (!head2)
    return head1;

  //循環變量的初始化,q指向鏈表head1中的當前結點,p為q的前驅。
  p = NULL;
  q = head1;
  while (head2)
  {
    //t為待插入結點。
    t = head2;
    head2 = head2->next;
    //尋找插入位置,插入位置為p和q之間。
    for (;q  q->data = t->data; p = q, q = q->next);
    if (p == NULL)
      head1 = t;
    else
      p->next = t;
    t->next = q;
    //將結點t插入到p和q之間后,使p重新指向q的前驅。
    p = t;
  }
  return head1;
}

LinkList LinkMerge2(LinkList head1, LinkList head2)
{
  LinkList result;

  if (!head1)
    return head2;
  if (!head2)
    return head1;

  if (head1->data = head2->data)
  {
    result = head1;
    result->next = LinkMerge(head1->next, head2);
  }
  else
  {
    result = head2;
    result->next = LinkMerge(head1, head2->next);
  }
  return result;
}

/*
 * 鏈表分割函數。
 * 將鏈表head均分為兩部分head1和head2,若鏈表長度為奇數,多出的結點從屬于第一部分。
 * 實現方法:首先使指針slow/fast指向鏈首,
 * 然后使fast指針向前移動兩個結點的同時,slow指針向前移動一個結點,
 * 循環移動,直至fast指針指向鏈尾。結束時,slow指向鏈表head1的鏈尾。
 */
int LinkSplit(LinkList head, LinkList *head1, LinkList *head2)
{
  LinkList slow, fast;

  if (head == NULL || head->next == NULL)
  {
    *head1 = head;
    *head2 = NULL;
    return 0;
  }
  slow = head;
  fast = head->next;
  while (fast)
  {
    fast = fast->next;
    if (fast)
    {
      fast = fast->next;
      slow = slow->next;
    }
  }
  *head1 = head;
  *head2 = slow->next;

  //注意:一定要將鏈表head1的鏈尾置空。
  slow->next = NULL;
  return 0;
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:
  • js單向鏈表的具體實現實例
  • JavaScript 雙向鏈表操作實例分析【創建、增加、查找、刪除等】
  • JavaScript將數組轉換為鏈表的方法
  • JS中的算法與數據結構之鏈表(Linked-list)實例詳解
  • JS實現的合并兩個有序鏈表算法示例
  • 使用JavaScript實現鏈表的數據結構的代碼
  • JavaScript數據結構之鏈表的實現
  • javascript循環鏈表之約瑟夫環的實現方法
  • JS使用單鏈表統計英語單詞出現次數
  • JavaScript封裝單向鏈表的示例代碼

標簽:烏蘭察布 吉林 臨汾 自貢 開封 銅川 白銀 山南

巨人網絡通訊聲明:本文標題《JavaScript實現鏈表插入排序和鏈表歸并排序》,本文關鍵詞  JavaScript,實現,鏈表,插入,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《JavaScript實現鏈表插入排序和鏈表歸并排序》相關的同類信息!
  • 本頁收集關于JavaScript實現鏈表插入排序和鏈表歸并排序的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 芜湖县| 大余县| 保德县| 文安县| 罗源县| 青岛市| 玛曲县| 荆州市| 江阴市| 定陶县| 宁陵县| 龙门县| 永康市| 栖霞市| 儋州市| 璧山县| 苏尼特左旗| 鹰潭市| 嘉兴市| 临城县| 丰台区| 高州市| 商水县| 阿拉善左旗| 五寨县| 桐柏县| 西安市| 延川县| 崇信县| 申扎县| 鸡西市| 田林县| 邯郸县| 抚松县| 尉氏县| 禹州市| 仙游县| 甘肃省| 泽库县| 焦作市| 奈曼旗|