链表排序——选择排序法(纯C语言版)

[cpp]  view plain  copy
 print ?
  1. /********************************* 链表的排序  *******************************************/  
  2. /* 
  3. ========================== 
  4.  功能:选择排序(由小到大) 
  5.  返回:指向链表表头的指针 
  6. ========================== 
  7.  
  8.  选择排序的基本思想就是反复从还未排好序的那些节点中, 
  9.  选出键值(就是用它排序的字段,我们取学号num为键值)最小的节点, 
  10.  依次重新组合成一个链表。 
  11.  
  12.  我认为写链表这类程序,关键是理解: 
  13.  head存储的是第一个节点的地址,head->next存储的是第二个节点的地址; 
  14.  任 意一个节点p的地址,只能通过它前一个节点的next来求得。 
  15.  
  16. 单向链表的选择排序图示: 
  17. ---->[1]---->[3]---->[2]...----> [n]---->[NULL](原链表) 
  18. head   1->next  3->next  2->next   n->next 
  19.  
  20. ---->[NULL](空链表) 
  21. first 
  22. tail 
  23. ---->[1]---->[2]---->[3]...---->[n]---->[NULL](排序后链表) 
  24. first   1->next  2->next  3->next   tail->next 
  25.  
  26. 1、先在原链表中找最小的,找到一个后就把它放到另一个空的链表中; 
  27. 2、空链表中安放第一个进来的节点,产生一个有序链表,并且让它在原链表中分离出来(此时要注意原链表中出来的是第一个节点还是中间其它节点); 
  28. 3、继续在原链表中找下一个最小的,找到后把它放入有序链表的尾指针的next,然后它变成其尾指针; 
  29. */  
  30. struct student *SelectSort(struct student *head)  
  31. {  
  32.     struct student *pfirst;      /* 排列后有序链的表头指针 */  
  33.     struct student *ptail;       /* 排列后有序链的表尾指针 */  
  34.     struct student *pminBefore;  /* 保留键值更小的节点的前驱节点的指针 */  
  35.     struct student *pmin;        /* 存储最小节点   */  
  36.     struct student *p;           /* 当前比较的节点 */  
  37.    
  38.     pfirst = NULL;  
  39.     while (head != NULL)         /*在链表中找键值最小的节点。*/  
  40.     {  
  41.     /* 注意:这里for语句就是体现选择排序思想的地方 */  
  42.         for (p = head, pmin = head; p->next != NULL; p = p->next) /*循环遍历链表中的节点,找出此时最小的节点。*/  
  43.         {  
  44.             if (p->next->num < pmin->num) /*找到一个比当前min小的节点。*/  
  45.             {  
  46.                 pminBefore = p;           /*保存找到节点的前驱节点:显然p->next的前驱节点是p。*/  
  47.                 pmin       = p->next;     /*保存键值更小的节点。*/  
  48.             }  
  49.         }  
  50.     
  51.     /*上面for语句结束后,就要做两件事;一是把它放入有序链表中;二是根据相应的条件判断,安排它离开原来的链表。*/  
  52.       
  53.         /*第一件事*/  
  54.         if (pfirst == NULL)     /* 如果有序链表目前还是一个空链表                      */  
  55.         {  
  56.             pfirst = pmin;      /* 第一次找到键值最小的节点。                          */  
  57.             ptail  = pmin;      /* 注意:尾指针让它指向最后的一个节点。                */  
  58.         }  
  59.         else                    /* 有序链表中已经有节点                                */  
  60.         {  
  61.             ptail->next = pmin; /* 把刚找到的最小节点放到最后,即让尾指针的next指向它。*/  
  62.             ptail = pmin;       /* 尾指针也要指向它。                                  */  
  63.         }  
  64.   
  65.         /*第二件事*/  
  66.         if (pmin == head)        /* 如果找到的最小节点就是第一个节点                    */  
  67.         {  
  68.             head = head->next;   /* 显然让head指向原head->next,即第二个节点,就OK       */  
  69.         }  
  70.         else /*如果不是第一个节点*/  
  71.         {  
  72.             pminBefore->next = pmin->next; /*前次最小节点的next指向当前pmin的next,这样就让pmin离开了原链表。*/  
  73.         }  
  74.     }  
  75.   
  76.     if (pfirst != NULL)     /*循环结束得到有序链表first                */  
  77.     {  
  78.         ptail->next = NULL; /*单向链表的最后一个节点的next应该指向NULL */   
  79.     }  
  80.     head = pfirst;  
  81.     return head;  
  82. }  
  • 20
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值