有序链表(或无序链表)的合并

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

运行结果如下图:

原文地址:https://www.cnblogs.com/scud001/p/4438863.html