ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

hw:递归与非递归的转化与使用

2021-10-31 16:30:54  阅读:166  来源: 互联网

标签:info return 递归 int hw GenListNode putInf 与非


第一题:设计一个递归算法,从自然数1、2、…、m中任取k个数的所有组合

#include<iostream>
#include<vector>
using namespace std;
vector<int> putInf;//每一种可能的方案
vector<vector<int>> ans;//存储可行方案  !!!(多结果的记录)


//vector<vector<int>>&
void combination(int m,int k)//m自然数个数,k,取k个数
{
	if (m == k)
	{
		for (int i = m; i > 0; i--)
		{
			putInf.push_back(i);
		}
		ans.push_back(putInf);
		for (int i = 0; i < m; i++)
		{
			putInf.pop_back();
		}
	}
	else if (k == 0)
	{
		ans.push_back(putInf);
	}
	else
	{
		putInf.push_back(m);//选中第m个数
		combination(m - 1, k - 1);//第m个数在组合中 递归
		putInf.pop_back();//还原到结点处

		combination(m - 1, k);//第m个数不在组合中
	}	
}

int main()
{
	int m, k,j=1;//num记录共有多少种组合数
	cout << "从1~m个自然数中选择k个数,请输入吗m,k" << endl;
	cin >> m >> k;
	combination(m, k);
	cout << "共" << ans.size() << "种方案\n具体方案如下如下:\n" << endl;
	for (vector<vector<int>>::iterator it = ans.begin(); it != ans.end(); it++) {
		cout << "第" << j++ << "种方案, 结果为 " << endl;
		for (int i = 0; i < it->size(); i++) {
			cout << (*it)[i]  << "  ";
		}
		cout << endl;
	}
	return 0;
}

第二题:已知Ackerman函数定义如下: (1) 写出递归算法; (2)利用栈,写出非递归算法;

 

 

//注意对于ackman函数,输出值增长速度非常快,仅是对于(4,3)的输出已大得不能准确计算
#include<iostream>
#include<stack>

using namespace std;

//递归算法  按照公式输入即可
int akm1(int m, int n)
{
	if (m == 0)
		return n + 1;
	else if (n == 0)
		return akm1(m - 1, 1);
	else
		return akm1(m - 1, akm1(m, n - 1));
}

//非递归算法 线性递归转化为非递归
//始终保持n在计算位,将m入栈
int akm2(int m, int n)
{
	stack<int> s;
	s.push(m);
	while (!s.empty())
	{
		m = s.top();
		s.pop();
		if (m == 0)//m=0,akm(m,n)=n+1
		{
			n++;
		}
		else if (n == 0)//m!=0,n=0, akm(m,n)=akm(m-1,1)
		{
			s.push(m - 1);
			n = 1;
		}
		else//m!=0, n!=0, akm(m,n)=  
		{
			s.push(m - 1);
			s.push(m);
			n--;
		}
	}
	return n;
}

int main()
{
	int m, n;
	cout << "请输入m,n" << endl;
	cin >> m >> n;
	cout << "递归算法结果为:"<<akm1(m, n) << endl;
	cout << "非递归算法结果为:" << akm2(m, n) << endl;
	return 0;
}

第三题:写一个判断两个广义表相等的递归算法

 

#include<iostream>
using namespace std;

template <class Type> class GenList;
template <class Type> class GenListNode {//广义表节点定义
    friend class Genlist;
private:
    int utype;       //=0/1/2
    GenListNode <Type>* tlink;     //指向同级的下一个结点 
    union {      //联合 
        int ref;    Type value;   //utype=0,在ref计数,utype=1,在value中储存值 
        GenListNode <Type>* hlink;     //utype=2储存子表头节点 
    } info;
public:
    GenListNode() { info.utype(0), tlink(NULL), info.ref(0); }
    GenListNode(GenListNode<Type>* p)
    {
        utype = p->utype;  tlink = p->tlink;  info = p->info;
    }
};
template <class Type> class GenList {
private:
    GenListNode <Type>* first;
    bool Equal(GenListNode<Type>* s, GenListNode<Type>* t);
};

template<class Type>
bool GenList<Type>::Equal(GenListNode<Type>* s, GenListNode<Type>* t)
{
    if (s != NULL && t != NULL)//两广义表均不为空
    {
        if (s->info.ref == t->info.ref)
        {
            s = s->tlink; t = t->tlink;
            while (s != NULL && t != NULL)//依次比较
            {
                if ((s->utype == 1 && t->utype == 1 && s->info.value == t->info.value) || (s->utype == 2 && t->type == 2 && Equal(s->info.hlink, t->info.hlink)))//若储存子表,递归比较
                {
                    s = s->tlink; t = t->tlink;
                }//当前节点相等则后移
                else  return false;
            }
            if (s == NULL && t == NULL)return true;//完成全循环则相等
        }
        else return false;
    }
    else if (s == NULL && t == NULL) return true;//都为空表,相等
    else return false;//一个空一个不空,不相等
}

 

 第四题: 皇后问题:

用 n 行 n 列的矩阵表示一个国际象棋棋盘,若两个皇后位于同一行、同一列、同一对角线上(包括下图所示的各主对角线和次对角线),则称为它们为互相攻击。n皇后问题是指找到这 n 个皇后的互不攻击的布局。请给出解决这个问题的递归算法。

//2021.10.31
//递归解决n皇后问题
//思路:先写出合法判断的条件,之后按照空间树求解,在节点处调用递归,注意求解后结果的保存与记录数值的还原

#include <iostream>
#include <vector>
using namespace std;
#define N 256
int n;//记录n皇后值
vector<int> putInf;//每一行皇后的置放位置情况
int used[N] = { 0 };//每一列只能有一个皇后,记录每一列的状态
vector<vector<int>> ans;//存储可行方案  !!!(多结果的记录)
int curRow = 0;//当前待放皇后的行数

bool judgeLegalPut(int& curRow, int col) {//判断在curRow行的col列放置皇后是否合法
	for (int i = curRow - 1; i >= 0; i--) {
		//在queueAssign中已经排除了皇后处于同一行及同一列的情况
		//因此在这里只需要判断皇后是否成斜线即可
		if (curRow - i == abs(col - putInf[i])) {
			//当前位置与之前的皇后处于同一斜线上
			return false;
		}
	}
	return true;
}

void queensAssign(int curRow) {//一般递归函数输入都带有记录当前进度的数
	if (curRow >= n) {//完成n行遍历,递归结束,收集结果
		ans.push_back(putInf);
		return;
	}
	//i : 当前行皇后准备放的列数
	for (int i = 0; i < n; ++i) {//curRow行i列的位置
		if (used[i]) continue;//位置被使用过,直接跳过  排除了两皇后处于同一列的情况
		if (judgeLegalPut(curRow, i)) {
			//当前位置置放与之前不冲突 将皇后加入
			used[i] = true;
			putInf.push_back(i);
			queensAssign(curRow + 1);
			//在之前的递归中,已经得到了这种情况下的完整解并储存
			//一次要把used数组与putInf还原到上一步(即空间树的上一个分叉处),以便下一个分支的求解
			used[i] = false;
			putInf.pop_back();
		}
	}
}


void printChessBoard(vector<int>& vec) {//输出模拟棋盘
	cout << endl;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (j != vec[i])
				cout << "○";
			else
				cout << "●";
		}cout << endl;
	}cout << endl;
}

int main() {
	cout << "请输入n皇后问题的规模" << endl;
	cin >> n;
	queensAssign(0);
	int j = 1;
	cout << n << "皇后问题,共"<<ans.size()<<"种方案\n具体方案如下如下:\n" << endl;
	for (vector<vector<int>>::iterator it = ans.begin(); it != ans.end();it++) {
		cout << "第" << j++ << "种放置方案, 皇后被放于 " << endl;
		for (int i = 0; i < it->size(); i++) {
			cout << (*it)[i] + 1 << "  ";
		}cout << "列" << endl;
		cout << endl << "棋盘布局如下↓" << endl;
		printChessBoard(*it);
	}
	return 0;
}

 

 

标签:info,return,递归,int,hw,GenListNode,putInf,与非
来源: https://blog.csdn.net/m0_52286166/article/details/121065840

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有