第44课 递归的思想与应用(中)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第44课 递归的思想与应用(中)相关的知识,希望对你有一定的参考价值。
1. 单向链表的转置
【编程实验】单向链表的转置(Node* reverse(Node* list))
2. 单向排序链表的合并
【编程实验】单向排序链表的合并(Node* merge(Node* list1, Node* list2))
3. 汉诺塔问题
(1)游戏规则
①将木块借助B柱由A柱移动C柱
②每次只能移动一个土块
③只能出现小土块在大木块之上
(2)递归求解的问题分解
①将n-1个木块借助C柱由A移动到B柱。
②将最底层的唯一木块直接移动到C柱
③将n-1个木块借助A柱由B柱移动到C柱
【编程实验】汉诺塔问题求解(void HanoiTower(int n, char a, char b, char c))
4. 全排列问题
【编程实验】全排列的递归解法(void permutation(char* s))
//main.cpp
#include <iostream> #include <cstring> using namespace std; struct Node { int value; Node* next; }; //创建无表头结点的单链表(己填充数据):v结点的值,len链表长度 Node* create_list(int v, int len) { Node* ret = NULL; Node* slider = NULL; for(int i=0; i<len; i++){ Node* node = new Node(); node->value = v++; node->next = NULL; //每创建好一个节点,slider指向这个节点 if( slider == NULL ){ slider = node; ret = node; }else{ slider->next = node; slider = node; } } return ret; } void destroy_list(Node* list) { while(list){ Node* del = list; list = list->next; delete del; } } //打印链表的内容 void print_list(Node* list) { while(list){ cout << list->value << "->"; list = list->next; } cout << "NULL" << endl; } //单链表转置(递归法) Node* reverse(Node* list) { //递归出口 if((list == NULL) || (list->next == NULL)){ return list; }else{ Node* guard = list->next; //指向反转前的子链表第1个结点 Node* ret = reverse(list->next); //转置子链表 guard->next = list; //反转后,guard变成子链表的最后一个结点 list->next = NULL; return ret; } } //单向排序链表的合并 Node* merge(Node* list1, Node* list2) { //递归出口 if(list1 == NULL) return list2; if(list2 == NULL) return list2; //取出子链表的第1个结点并比较 if(list1->value < list2->value){ //由于当前list1结点的值较小,取出当前结点,其next //指向由该结点后继的子链表和list2合并的新链表 list1->next = merge(list1->next, list2); return list1; }else{ //list2当前结点的值较小 list2->next = merge(list1, list2->next); return list2; } } //汉诺塔 void HanoiTower(int n, char a, char b, char c) { if(n == 1){ cout << a << "-->" << c << endl; }else{ HanoiTower(n-1, a, c, b); //将n-1块,从a柱借c柱移动到b柱 HanoiTower(1, a, b, c); //将a柱剩下的最后一块移到c柱上 HanoiTower(n-1, b, a, c); //将b柱中的n-1块借助a柱移到c柱。 } } //全排列 void permutation(char* s, char* e) { if(*s == ‘\\0‘) { cout << e << endl;//打印出全排列好的字符串 }else{ int len = strlen(s); //如将abc //1.第1轮:将abc变成以a开头,然后全排列bc //2.第2轮:将abc变成以b开头,然后全排列ac //3.第3轮:将abc变成以c开头,然后全排列ba for(int i=0; i<len; i++){ if((i == 0) || (s[0] != s[i])){ //去重复,如aba就不交换两个a swap(s[0], s[i]); //以s[0]开头(每轮会变化),全排列其后的子串。 permutation(s+1, e); //全排列子串 swap(s[0], s[i]); //恢复为原来的串,如abc,以便下一轮全排列。 } } } } int main() { //测试:单链表转置 Node* list = create_list(1, 10); print_list(list); list = reverse(list); print_list(list); destroy_list(list); //测试:单向排序链表的合并 Node* list1 = create_list(1,5); Node* list2 = create_list(3,7); print_list(list1); print_list(list2); Node* ret = merge(list1, list2); print_list(ret); destroy_list(ret); //测试:汉诺塔 HanoiTower(3, ‘a‘, ‘b‘, ‘c‘); //测试:全排列 char s[]="aabc"; permutation(s, s); return 0; } /*测试结果: 1->2->3->4->5->6->7->8->9->10->NULL 10->9->8->7->6->5->4->3->2->1->NULL 1->2->3->4->5->NULL 3->4->5->6->7->8->9->NULL 1->2->3->3->4->4->5->5->6->7->8->9->NULL a-->c a-->b c-->b a-->c b-->a b-->c a-->c aabc aacb abac abca acba acab baac baca bcaa caba caab cbaa */
以上是关于第44课 递归的思想与应用(中)的主要内容,如果未能解决你的问题,请参考以下文章