zoukankan      html  css  js  c++  java
  • 有序链表(或无序链表)的合并

    最近博主离职找工作了,正好赶上最美离职信。呵呵,小伙伴纷纷借着这个东风给予鼓励。在此表示无限次的感谢ing。

    其实离职,对于非计算机科班出身,过了30岁,有了家庭,还有了小孩,还要还房货。压力是可想而知的。不管压力多大,是不是能坚持到黎明,看见曙光;还是要走出去试一试。看一看。现在有一部分公司,对技术过于不认可。老板和领导经常说,你不要跟我讲技术,我只关心这个软件或项目有没有亮点,能不能挣钱。只有你有亮点,能挣钱,技术不是问题。

    唉,这种想法试问一下,造时速5000公里的动车能挣钱,还有亮点,国家还有政策支持,那也得有这个技术实力才行对吧。现在流行大数据,云时代,假设给我们1000万条数据,我们如何加工成客户需要的,如果没有这个实力,还是先修炼内功。把技术做好吧。

    世界那么大,我想找一个稍微看得起技术的环境。扯远了,回到正题了。

    上次在写链表逆序的时候,收了一个园友的回复说,递归要比while循环看着直观。本人感谢这位园友的回复,其实个人觉得递归代码简单,逻辑性较好,代码跟踪与调试要求较高。

    但在生产过程中,结合一定的业务逻辑进行处理时,给维护增加了一些复杂度。写个while死循环倒也是简单明了。呵呵,关于是不是用递归,何时用递归这是一个无解的问题。望大家勿喷。

    上代码了:qt,c语言。

    代码里面包含了递归和非递归的对比。以及链表的排序,插入、随机key值的生成等。本代码中,递归合并节点的关键是要记录前一个节点,同时再比较两个链表的头节点,节点pPrev的next指针,指向key值小的节点。同时将key值小的链表头向后移动一个位置,然后再进行下一次的递归合并。直到其中的一个链表为空。

      1 #include <QCoreApplication>
      2 #include <time.h>
      3 
      4 const int MAX_CHAR = 30;
      5 const int MAX_VALUE = 100;
      6 //类型
      7 enum lsType{
      8     Composite,
      9     Prime
     10 };
     11 
     12 //节点
     13 typedef struct Node{
     14     int key;
     15     char value[MAX_CHAR];
     16     struct Node *next;
     17 }NodeList;
     18 
     19 //生成链表
     20 Node* generateList(lsType type, int num);
     21 //生成链表(按递归方式)
     22 Node* generateListByRecursion(lsType type, int num);
     23 
     24 //链表的合并
     25 Node* mergeList(Node *list1, Node* list2);
     26 //链表的递归合并
     27 Node* recursionMergeList(Node* pPrev, NodeList *list1, NodeList* list2);
     28 //打印链表
     29 void printList(Node *pNode);
     30 //判断一个数是否为质数
     31 bool isPrime(unsigned long n);
     32 //获得随机质数
     33 int getRandPrime(int Max);
     34 //释放链表
     35 void freeList(Node *pList);
     36 //链表的插入(while循环)
     37 Node* InsertNode(NodeList* list, Node *pNode);
     38 //链表的插入(递归入口)
     39 Node* InsertNodeRecMain(NodeList* list, Node *pNode);
     40 //链表的插入(递归体)
     41 Node* InsertNodeByRecursion(Node* list, Node* pInsert, Node* pPrev);
     42 
     43 
     44 int main(int argc, char *argv[])
     45 {
     46     QCoreApplication a(argc, argv);
     47     //随机数的种子值
     48     srand((unsigned)time(NULL));
     49     //普通生成方式
     50     //Node* pList1 = generateList(Composite, 10);
     51     //Node* pList2 = generateList(Prime, 10);
     52     printf("节点列表1(插入过程进行排序)
    ");
     53     //递归生成方式
     54     Node* pList1 = generateListByRecursion(Composite, 5);
     55     Node* pList2 = generateListByRecursion(Prime, 5);
     56     printList(pList1);    
     57     printf("节点列表2(插入过程进行排序)
    ");
     58     printList(pList2);
     59     Node* pList3 = mergeList(pList1, pList2);
     60     printf("合并后的节点列表为:
    ");
     61     printList(pList3);
     62     return a.exec();
     63 }
     64 
     65 /**
     66   * @函数名:generateList
     67   * @参数:type:根据不同的状态码,生成对应的链表
     68   *       num:链表的个数
     69   * @返回值:生成的链表
     70   * @用途: 生成链表
     71   * @作者:yangfy
     72   */
     73 Node* generateList(lsType type, int num)
     74 {
     75     int nrand;
     76     //下一节点
     77     Node* pHead = NULL, *pPrev = NULL;
     78     if(type == Composite){
     79         //生成头节点
     80         pHead = (Node*)malloc(sizeof(struct Node));
     81         nrand = rand() % MAX_VALUE + 2;
     82         pHead->key = nrand % 2 ? nrand - 1 : nrand;
     83         snprintf(pHead->value, MAX_CHAR - 1, "值为:%c元素", 65);
     84         pHead->next = NULL;
     85         pPrev = pHead;
     86         //生成数组
     87         for(int i = 1; i < num; i++){
     88             Node* pNode = (Node*)malloc(sizeof(struct Node));
     89             pNode->next = NULL;
     90             //100以内的合数
     91             nrand = rand() % MAX_VALUE + 2;
     92             pNode->key = nrand % 2 ? nrand - 1 : nrand;            
     93             snprintf(pNode->value, MAX_CHAR - 1, "值为:%c元素", 65 + i);
     94             pHead = InsertNode(pHead, pNode);
     95             //next节点的指定
     96             pPrev->next = pNode;
     97             pPrev = pNode;
     98         }
     99         return pHead;
    100 
    101     } else if(type == Prime){
    102         //生成头节点
    103         pHead = (Node*)malloc(sizeof(struct Node));
    104         pHead->key = getRandPrime(MAX_VALUE);
    105         pHead->next = NULL;
    106         snprintf(pHead->value, MAX_CHAR - 1, "值为:%c元素", 65);
    107         pPrev = pHead;
    108         //生成数组
    109         for(int i =1; i < num; i++){
    110             Node* pNode = (Node*)malloc(sizeof(struct Node));
    111             pNode->next = NULL;
    112             //获得质数
    113             pNode->key = getRandPrime(MAX_VALUE);
    114             snprintf(pNode->value, MAX_CHAR - 1, "值为:%c元素", 65 + i);
    115             pHead = InsertNode(pHead, pNode);
    116             //next节点的指定
    117             pPrev->next = pNode;
    118             pPrev = pNode;
    119         }
    120         return pHead;
    121     }
    122     return NULL;
    123 }
    124 
    125 /**
    126   * @函数名:generateListByRecursion
    127   * @参数:type 生成类型(质数、合数之分)
    128   *       num 节点数量
    129   * @返回值:生成的链表
    130   * @用途:生成指定数量、指定用途的链表
    131   * @作者:yangfy
    132   */
    133 Node* generateListByRecursion(lsType type, int num)
    134 {
    135     int nrand;
    136     //下一节点
    137     Node* pHead = NULL;
    138     if(type == Composite){
    139         //生成头节点
    140         pHead = (Node*)malloc(sizeof(struct Node));
    141         nrand = rand() % MAX_VALUE + 2;
    142         pHead->key = nrand % 2 ? nrand - 1 : nrand;
    143         snprintf(pHead->value, MAX_CHAR - 1, "值为:%c1元素", 65);
    144         pHead->next = NULL;
    145         //生成数组
    146         for(int i = 1; i < num; i++){
    147             Node* pNode = (Node*)malloc(sizeof(struct Node));
    148             pNode->next = NULL;
    149             //100以内的合数
    150             nrand = rand() % MAX_VALUE + 2;
    151             pNode->key = nrand % 2 ? nrand - 1 : nrand;
    152             snprintf(pNode->value, MAX_CHAR - 1, "值为:%c1元素", 65 + i);
    153             pHead = InsertNodeRecMain(pHead, pNode);
    154         }
    155         return pHead;
    156 
    157     } else if(type == Prime){
    158         //生成头节点
    159         pHead = (Node*)malloc(sizeof(struct Node));
    160         pHead->key = getRandPrime(MAX_VALUE);
    161         snprintf(pHead->value, MAX_CHAR - 1, "值为:%c2元素", 65);
    162         pHead->next = NULL;
    163         //生成数组
    164         for(int i =1; i < num; i++){
    165             Node* pNode = (Node*)malloc(sizeof(struct Node));
    166             pNode->next = NULL;
    167             //获得质数
    168             pNode->key = getRandPrime(MAX_VALUE);
    169             snprintf(pNode->value, MAX_CHAR - 1, "值为:%c2元素", 65 + i);
    170             pHead = InsertNodeRecMain(pHead, pNode);
    171         }
    172         return pHead;
    173     }
    174     return NULL;
    175 }
    176 
    177 /**
    178   * @函数名:isPrime
    179   * @参数:n:要判断的数
    180   * @返回值:是否为质数
    181   * @用途:判断一个数是否为质数
    182   * @作者:yangfy
    183   */
    184 bool isPrime(unsigned long n)
    185 {
    186     if (n <= 3){
    187         return n > 1;
    188     } else if (n % 2 == 0 || n % 3 == 0) {
    189         return false;
    190     } else {
    191         for (unsigned short i = 5; i * i <= n; i += 6) {
    192             if (n % i == 0 || n % (i + 2) == 0) {
    193                 return false;
    194             }
    195         }
    196         return true;
    197     }
    198 }
    199 /**
    200   * @函数名:getRandPrime
    201   * @参数:nMax:随机的最大数
    202   * @返回值:随机生成的质数
    203   * @用途:随机生成MAX以内的质数
    204   * @作者:yangfy
    205   */
    206 int getRandPrime(int Max)
    207 {
    208     int nRand;
    209     while (1) {
    210         //获取100以内的质数
    211         nRand = rand() % Max + 1;
    212         if (isPrime(nRand))
    213             return nRand;
    214     }
    215 }
    216 
    217 /**
    218   * @函数名:InsertNode
    219   * @参数:list要插入节点的链表
    220   *       pNode要插入的节点
    221   * @返回值:插入完成后的链表
    222   * @用途:将指定节点插入到链表中
    223   * @作者:yangfy
    224   */
    225 Node* InsertNode(NodeList* list, Node *pNode)
    226 {
    227     Node* pHead = list;
    228     //异常判断
    229     if(list == NULL)
    230         return NULL;
    231     if(pNode == NULL)
    232         return pHead;
    233     //头节点处理
    234     if(pHead->key > pNode->key){
    235         pNode->next = pHead;
    236         return pNode;
    237     }
    238     //节点插入
    239     while (true) {
    240         if(pHead == NULL){
    241             break;
    242         }
    243         //尾节点
    244         if(pHead->next == NULL){
    245             pHead->next = pNode;
    246             break;
    247         }
    248         else if(pHead->next->key > pNode->key){
    249            pNode->next = pHead->next;
    250            pHead->next = pNode;
    251            break;
    252         }
    253         pHead = pHead->next;
    254     }
    255     return list;
    256 }
    257 
    258 /**
    259   * @函数名:InsertNodeRecMain
    260   * @参数:list要插入节点的链表
    261   *       pNode要插入的节点
    262   * @返回值:插入完成后的链表
    263   * @用途:通过递归方式将节点插入链表
    264   *       将递归中不通用的部分分离出来,递归链表的通用部分
    265   * @作者:yangfy
    266   */
    267 Node* InsertNodeRecMain(NodeList *list, Node *pNode)
    268 {
    269     //节点判断
    270     if(list == NULL) return pNode;
    271     if(pNode == NULL) return list;
    272     if(list->key > pNode->key){
    273         pNode->next = list;
    274         return pNode;
    275     }
    276     return InsertNodeByRecursion(list, pNode, NULL);
    277 }
    278 /**
    279   * @函数名:InsertNodeByRecursion
    280   * @参数:list要插入节点的链表
    281   *       pInsert:要插入的节点
    282   *       pPrev:插入位置的前一个节点(要把本节点next指向为插入节点)
    283   * @返回值:插入成功的链表
    284   * @用途:递归查找可以插入的节点位置,插入节点
    285   * @作者:yangfy
    286   */
    287 Node* InsertNodeByRecursion(Node *list, Node *pInsert, Node *pPrev)
    288 {
    289     Node* pResult = list;
    290     if(list != NULL){
    291         if(list->key > pInsert->key){
    292             pInsert->next = list;
    293             pPrev->next = pInsert;
    294         }
    295         else{
    296             InsertNodeByRecursion(list->next, pInsert, list);
    297         }
    298     } else{
    299         if(pPrev != NULL){
    300             pPrev->next = pInsert;
    301         }
    302     }
    303     return pResult;
    304 }
    305 /**
    306   * @函数名:mergeList
    307   * @参数:list1:要合并的链表1
    308   *       list2:要合并的链表2
    309   * @返回值:合并成功的链表
    310   * @用途:确定链表合并的开始位置(合理),是不是可以理解为确定始基
    311   *       调用递归函数合并节点
    312   * @作者:yangfy
    313   */
    314 Node* mergeList(Node *list1, Node* list2){
    315     Node* pPrev = NULL;
    316     if(list1->key < list2->key){
    317         pPrev = list1;
    318         list1 = list1->next;
    319     }else{
    320         pPrev = list2;
    321         list2 = list2->next;
    322     }
    323     return recursionMergeList(pPrev, list1, list2);
    324 }
    325 /**
    326   * @函数名:recursionMergeList
    327   * @参数:pPrev:要合并的前一个节点
    328   *       list1:链表1
    329   *       list2:链表2
    330   * @返回值:前一个节点
    331   * @用途:递归调用进行链表的合并
    332   * @作者:yangfy
    333   */
    334 Node* recursionMergeList(Node *pPrev, NodeList *list1, NodeList *list2)
    335 {
    336     if(list1 == NULL){
    337         pPrev->next = list2;
    338         return pPrev;
    339     }
    340     if(list2 == NULL){
    341         pPrev->next = list1;
    342         return pPrev;
    343     }
    344     if(list1->key < list2->key){
    345         pPrev->next = list1;
    346         list1 = list1->next;
    347         recursionMergeList(pPrev->next, list1, list2);
    348     } else {
    349         pPrev->next = list2;
    350         list2 = list2->next;
    351         recursionMergeList(pPrev->next, list1, list2);
    352     }
    353     return pPrev;
    354 }
    355 /**
    356   * @函数名:printList
    357   * @参数:pNode:要打印的链表头
    358   * @返回值:无
    359   * @用途:打印链表
    360   * @作者:yangfy
    361   */
    362 void printList(Node *pNode)
    363 {
    364     while (pNode != NULL) {
    365         if (pNode->next != NULL)
    366             printf("当前节点key为:%d, -->%s; (下一节点key为%d, -->%s)
    ", pNode->key, pNode->value, pNode->next->key, pNode->next->value);
    367         else
    368             printf("当前节点key为:%d, -->%s; 下一节点为NULL
    ", pNode->key, pNode->value);
    369         pNode = pNode->next;
    370     }
    371 }
    372 /**
    373   * @函数名:freeList
    374   * @参数:pList:要释放的链表
    375   * @返回值:无
    376   * @用途:释放链表
    377   * @作者:yangfy
    378   */
    379 void freeList(Node *pList)
    380 {
    381     Node *pNode = NULL;
    382     while (pList != NULL) {
    383         pNode = pList;
    384         pList = pList->next;
    385         free(pNode);
    386         pNode = NULL;
    387     }
    388 }

    运行结果如下图:

  • 相关阅读:
    谈谈iOS开发如何写个人中心这类页面--静态tableView页面的编写
    H5活动产品设计指南基础版
    提高你的Java代码质量吧:使用valueof前必须进行校验
    最新VMware Workstation 10注册码,绝对可用!
    ORACLE 使用RMAN管理归档日志 archived log
    hdu 2072 单词数
    【早盘必读】9.13证券市场要闻(附股)
    Java程序性能优化
    CSS3媒体查询(Media Queries)
    [cocos2d-x]用CCSpriteBatchNode进行文理贴图的优化
  • 原文地址:https://www.cnblogs.com/scud001/p/4438863.html
Copyright © 2011-2022 走看看