组合数学实验——生成{1,2,……,n}的排列的算法

只愿长相守 提交于 2020-04-15 15:39:22

【推荐阅读】微服务还能火多久?>>>

同前几篇博客

算法:组合数学中文第4版 机械工业出版社 P57

这个版本好像小范围发布过,这么多注释......

//////////////////////////////////////////////
//                                          //
//  Project Name: Permutation               //
//                                          //
//  File Name: permutation.h                //
//                                          //
//  Author: Victor Zhang                    //
//                                          //
//  ID: 21*****92                           //
//                                          //
//  Create Date: March 23. 2009             //
//                                          //
//////////////////////////////////////////////

#include <iostream>

using namespace std;

#ifndef PERMUTATION_H
#define PERMUTATION_H

struct unit//定义元素结构
{
	unit* pre;//指向前驱元素的指针
	bool arrowLeft;//元素箭头指向
	int value;//元素的值
	unit* next;//指向后继元素的指针
};

class Permutation_usr
{
private:
	unit* head;//链表头地址         (变量)
	int count;//链表长度            (变量)
	unit* activeUnit;//链表最大活动数所在元素的地址          (变量)

	bool newUnit(unit*, int);  //添加元素,并给新元素赋值    (函数)
	bool deleteUnit(unit*);    //删除指定地址的元素          (函数)

	bool setUnitArrow(bool, unit*);   //设置元素的箭头指向   (函数)
	bool getUnitArrow(unit*);         //获取元素的箭头指向   (函数)

	bool isActiveUnit(unit*);//判断元素是否为活动数          (函数)
	void findMaxActiveUnit();//查找最大活动数所在的元素      (函数)

	bool exchangeUnits(unit*);//交换目标元素和其箭头所指向的与其相邻的元素的位置(函数)

	bool setUnitValue(int, unit*);   //设置元素的值          (函数)
	int getUnitValue(unit*);         //获取元素的值          (函数)

public:
	Permutation_usr()//初始化链表
	{
		head = activeUnit = NULL;
		count = 0;
	};
	Permutation_usr(int);//初始化含n个元素的链表
	~Permutation_usr()//销毁链表
	{
		deleteAllUnits();//删除链表中的所有元素
		head = activeUnit = NULL;
		count = 0;
	};
	bool newUnits(int);//重建n个新元素,并自动赋值           (函数)
	bool deleteAllUnits();//删除head之后的所有元素           (函数)
	void prtQueue();//打印链表                               (函数)
	void proccess();//执行排列                               (函数)
};

#endif
//////////////////////////////////////////////
//                                          //
//  Project Name: Permutation               //
//                                          //
//  File Name: permutation.cpp              //
//                                          //
//  Author: Victor Zhang                    //
//                                          //
//  ID: 21*****92                           //
//                                          //
//  Create Date: March 23. 2009             //
//                                          //
//////////////////////////////////////////////

#include<iostream>

using namespace std;

#include"permutation.h"

Permutation_usr::Permutation_usr(int n)   //初始化含n个元素的链表
{
	this->activeUnit = this->head = NULL;
	this->count = 0;
	if (!(this->newUnits(n)))             /*若初始化失败给出提示信息*/
		cout<<"Error in creating units.\n";
};

bool Permutation_usr::newUnit(unit* a, int m_value)   //添加元素,并给新元素赋值
{
	unit* p_item = new unit;
	if (!(p_item)) return false;          /*若初始化失败,则返回失败*/
	p_item->arrowLeft = true;
	p_item->pre = a;
	p_item->value = m_value;
	if (this->count > 0)           /*判断链表中是否有元素*/
	{                              /*链表中已有元素*/
		p_item->next = a->next;
		if (a->next) a->next->pre = p_item;
		a->next = p_item;
	}
	else                           /*链表中无元素*/
	{
		p_item->next = NULL;
		this->head = p_item;       /*设置链表头地址*/
	};
	this->count++;
	return true;
};

bool Permutation_usr::newUnits(int n)    //重建n个新元素,并自动赋值
{
	unit* p_target = NULL;
	int i;
	if (n <= 0) return false;
	if (n < this->count)                 /*为提高重用时的效率,判断新建元素个数与原有元素之间的大小关系*/
	{                                    /*新链表元素个数小于原链表元素个数,则初始化元素箭头方向,并删除多余元素*/
		p_target = this->head;           //获取头地址
		for (i = 1; i <= n; i++)
		{
			head = head->next;           //获取要删除的多余元素的首地址
		};
		this->deleteAllUnits();          //删除多余元素
		head = p_target;                 //更新头地址
		for (i = 1; i<= n; i++)
		{
			this->setUnitArrow(true, p_target);         //初始化箭头方向
			if (i == n) p_target->next = NULL;          //末尾元素
			p_target = p_target->next;                  //移动指针
		};
	}
	else if (n == this->count)           /*新链表元素个数等于原链表元素个数,则初始化元素箭头方向*/
	{
		p_target = this->head;
		while (p_target)
		{
			this->setUnitArrow(true, p_target);
			p_target = p_target->next;
		};
	}
	else                                 /*新链表元素个数大于原链表元素个数,则初始化元素箭头方向,并删除多余元素*/
	{
		for (i = 1; i < this->count; i++)               //重置已有元素(不含末位)箭头方向
		{
			this->setUnitArrow(true, p_target);
			p_target = p_target->next;
		};
		this->setUnitArrow(true, p_target);             //重置末位元素箭头方向
		for (i = (this->count + 1); i <= n; i++)
		{
			if (!(this->newUnit(p_target, i))) return false;     //新建元素
			if (p_target) p_target = p_target->next;             //判断所创元素是否为链表首元素,不是则移动指针
			else p_target = this->head;                          //是则将指针指向该元素
		};
	};
	return true;
};

bool Permutation_usr::deleteAllUnits()    //删除head之后的所有元素
{
	unit* p_tmp, *p_nxt;
	p_tmp = p_nxt = head;
	while (p_tmp)
	{
		p_nxt = p_tmp->next;          //获取后继元素地址
		this->deleteUnit(p_tmp);      //删除当前元素
		p_tmp = p_nxt;                //将操作指针指向后继元素
	};
	return true;
};

bool Permutation_usr::deleteUnit(unit* a)    //删除指定地址的元素
{
	if (!(a)) return true;
	if (this->activeUnit == a) this->activeUnit = NULL;
	unit* m_nxt = a->next;                   //获取指定元素后继
	unit* m_pre = a->pre;                    //获取指定元素前驱
	if (m_nxt)                               //重新连接链表
	{
		if (m_pre)
		{
			m_nxt->pre = m_pre;
			m_pre->next = m_nxt;
		}
		else
		{
			m_nxt->pre = NULL;
			head = m_nxt;
		};
	}
	else
	{
		if (m_pre)
			m_pre->next = NULL;
		else
			this->head = NULL;
	};                                       //完成连接
	delete a;                                //删除元素
	this->count--;                           //计数器减一
	return true;
};

bool Permutation_usr::setUnitArrow(bool isArrowLeft, unit* a)    //设置元素的箭头指向
{
	if (a)
	{
		a->arrowLeft = isArrowLeft;
		return true;
	}
	else
		return false;
};

bool Permutation_usr::getUnitArrow(unit* a)    //获取元素的箭头指向
{
	if (a) return a->arrowLeft;
	return false;
};

void Permutation_usr::findMaxActiveUnit()    //查找最大活动数所在的元素
{
	unit* p_tmp;
	p_tmp = this->head;
	int m_curUnitValue = 0;
	int m_curMaxValue = 0;
	if (this->activeUnit) m_curMaxValue = this->activeUnit->value;         //获取当前最大活动数的值
	while (p_tmp)
	{
		m_curUnitValue = p_tmp->value;
		if (this->isActiveUnit(p_tmp) && m_curUnitValue > m_curMaxValue)   //当前指针所指元素为活动元素,且其值大于当前最大活动数的值
		{
			this->activeUnit = p_tmp;                                      //更改当前最大活动数的信息
			m_curMaxValue = this->activeUnit->value;
		};
		p_tmp = p_tmp->next;                                               //移动指针
	};
};

bool Permutation_usr::isActiveUnit(unit* a)    //判断元素是否为活动数
{
	if (!(a)) return false;
	if (a == this->head && this->getUnitArrow(a) == true) return false;
	if (a->next == NULL && this->getUnitArrow(a) == false) return false;
	if (this->getUnitArrow(a))
	{
		if (this->getUnitValue(a->pre) < a->value)
			return true;
	}
	else
	{
		if (this->getUnitValue(a->next) < a->value)
			return true;
	};
	return false;
};

bool Permutation_usr::exchangeUnits(unit* a)    //交换目标元素和其箭头所指向的与其相邻的元素的位置
{
	if (!(a)) return false;
	unit* p_pre, * p_next;
	p_pre = p_next = NULL;
	if (this->getUnitArrow(a) ==true)           //确定需要交换的两元素,并用指针指向此两元素
	{
		p_pre = a->pre;
		p_next = a;
	}
	else
	{
		p_pre = a;
		p_next = a->next;
	};                                          //元素确定及指向完毕
	if (!(p_pre && p_next)) return false;
	if (p_pre->pre)                             //开始重新构造链表。判断第一个元素是否有前驱
		p_pre->pre->next = p_next;              //有则将前驱的后继指针指向第二个元素
	else
		head = p_next;                          //没有则将链表头地址指向第二个元素
	if (p_next->next)                           //判断第二个元素是否有后继
		p_next->next->pre = p_pre;              //有则将后继的前驱指针指向第一个元素
	p_pre->next = p_next->next;                 //将第一个元素的后继指针指向第二个元素的后继
	p_next->pre = p_pre->pre;                   //将第二个元素的前驱指针指向第一个元素的前驱
	p_pre->pre = p_next;                        //将第一个元素的前驱指针指向第二个元素
	p_next->next = p_pre;                       //将第二个元素的后继指针指向第一个元素
	return true;                                //完成链表的重构
};

bool Permutation_usr::setUnitValue(int m_value, unit* a)    //设置元素的值
{
	if (!(a)) return false;
	a->value = m_value;
	return true;
};

int Permutation_usr::getUnitValue(unit* a)    //获取元素的值
{
	if (!(a)) return 0;
	return (a->value);
};

void Permutation_usr::prtQueue()    //打印链表
{
	unit* p = this->head;
	while (p)
	{
		cout<<p->value<<" ";
		p = p->next;
	};
	cout<<endl;
};

void Permutation_usr::proccess()    //执行排列
{
	this->prtQueue();
	unit* tmp = this->head;
	this->activeUnit = NULL;
	this->findMaxActiveUnit();                     //求最大活动数M
	while (this->activeUnit)                       //进入while循环
	{
		this->exchangeUnits(this->activeUnit);     //交换M和其箭头所指向的与其相邻的整数
		while (tmp)                                //交换所有满足p>m的整数p的方向
		{
			if (this->getUnitValue(tmp) > this->getUnitValue(this->activeUnit))
				this->setUnitArrow(!(this->getUnitArrow(tmp)),tmp);
			tmp = tmp->next;
		};
		tmp = this->head;                          //重置activeUnit、tmp
		this->activeUnit = NULL;
		this->prtQueue();                          //输出
		this->findMaxActiveUnit();                 //求最大活动数,继续循环
	};
};
//////////////////////////////////////////////
//                                          //
//  Project Name: Permutation               //
//                                          //
//  File Name: main.cpp                     //
//                                          //
//  Author: Victor Zhang                    //
//                                          //
//  ID: 21*****92                           //
//                                          //
//  Create Date: March 23. 2009             //
//                                          //
//////////////////////////////////////////////

#include<iostream>

using namespace std;

#include"permutation.h"

void main()
{
	int n = 0;
	cout<<"Please input n:";
	cin>>n;
	Permutation_usr a(n);
	a.proccess();
	system("pause");
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!