最近博主离职找工作了,正好赶上最美离职信。呵呵,小伙伴纷纷借着这个东风给予鼓励。在此表示无限次的感谢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(插入过程进行排序)\r\n"); 53 //递归生成方式 54 Node* pList1 = generateListByRecursion(Composite, 5); 55 Node* pList2 = generateListByRecursion(Prime, 5); 56 printList(pList1); 57 printf("节点列表2(插入过程进行排序)\r\n"); 58 printList(pList2); 59 Node* pList3 = mergeList(pList1, pList2); 60 printf("合并后的节点列表为:\r\n"); 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)\r\n", pNode->key, pNode->value, pNode->next->key, pNode->next->value); 367 else 368 printf("当前节点key为:%d, -->%s; 下一节点为NULL\r\n", 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 }
运行结果如下图: