算法导论实验——直方图问题和装箱问题

大家如果对算法导论以及其他信息感兴趣,可以加入学习交流群一起交流 948097478

问题1:直方图问题
从一个具有N个关键值的集合开始,要求输出不同关键值的列表以及每个关键值在集合中出现的次数(频率)。

问题分析:
用二叉搜索树保存集合的关键值以及关键值出现的次数。

源代码:

Tree.h
#include <iostream>   
#include <vector>  
using namespace std;
class TreeNode{
public:
	int key;
	int num=1;
	TreeNode* left;
	TreeNode* right;
	TreeNode* p;//指向父节点   
public:
	TreeNode();
	TreeNode(int val);
};

void inorder_tree_walk(TreeNode* x);
void tree_insert(TreeNode* T, TreeNode* z);


Tree.cpp
#include"tree.h"

TreeNode::TreeNode()
{
	key = 0;
	left = right = p = NULL;
}

TreeNode::TreeNode(int val)
{
	key = val;
	left = right = p = NULL;
}

void inorder_tree_walk(TreeNode* x)
{
	if (x != NULL)
	{
		inorder_tree_walk(x->left);
		cout << x->key << " ";
		cout << x->num << " ";
		cout << endl;
		inorder_tree_walk(x->right);
	}
	else
		return;
}

void tree_insert(TreeNode* T, TreeNode* z) //T是现在的BST的树根  
{
	TreeNode *y = NULL, *x = T;
	while (x)
	{
		y = x;
		if (z->key<x->key)
			x = x->left;
		else if (z->key == x->key) {
			x->num++;
			x = NULL;
		}
		else x = x->right;
	}
	z->p = y;
	if (!y)
		T = z;//T是颗空树  
	else if (z->key < y->key)
		y->left = z;
	else if (z->key == y->key);
	else y->right = z;
	//   return T;   
}


int main(){
	int x,n;
	cout << "输入二叉树节点个数:";
	cin >> n;
	cout << "请输入第1个节点:";
	cin >> x;
	TreeNode* T = new TreeNode(x);
	for (int i = 2; i <= n; i++){
		cout << "请输入第" << i << "个节点:";
		cin >> x;
		TreeNode* z = new TreeNode(x);
		tree_insert(T, z);
	}
	inorder_tree_walk(T);
}

运行结果:
在这里插入图片描述

问题2:装箱问题
有若干个容量为c的箱子和n个待装载入箱子的物品。物品i需占s[i]个单位。成功装载是指能把所有物品都装入箱子而不溢出。最优装载是指使用了最少箱子的成功装载。
箱子装载问题的四种解法:

1.最先匹配法:物品按1,2,…,n的顺序装入箱子。假设箱子从左至右排列。每一物品i放入可装载它的最左箱子。
2.最优匹配法:设cAvail[j]为箱子的可用容量。初始时,所有箱子的可负载容量为c。物品i放入具有cAvail且容量大于s[i]的箱子中
3.最先匹配递减法:此方法与最先匹配法类似,区别在于各物品首先按容量递减的次序排列,即对1<=i<n,有s[i]>=s[i+1]。
4.最优匹配递减法:此方法与最优匹配法类似,区别在于各物品首先按容量递减的次序排列,即对于1<=i<n,有s[i]>=s[i+1]。

设计思想:
使用贪心算法,先将所有物品按体积从大到小排序,每次拿出一个物品从第一个箱子开始遍历,如果可以放下,那么重新拿出一个物品再从第一个开始遍历,如果放不下,就开一个新箱子,将这个物品放在里面。

源代码:

#include <iostream>
using namespace std;
typedef struct {  //物品信息的结构体 
	int go;     //物品的编号 
	int gv;    //物品的体积 
}GOODS;

typedef struct Gnode{   //物品节点 
	int gnum;           //挂在链上的编号 
	struct Gnode *link; //指向下一个物品节点 
}GNODE;

typedef struct Gbox{   //箱子结构体 
	int reminder;     //剩余空间 
	GNODE *head;      //指向物品节点的第一个节点 
	struct Gbox *next;

}GBOX;

void sort(GOODS *goods, int n) //排序 
{
	int i, j;
	GOODS t;
	for (i = 0; i<n - 1; i++)
	for (j = i; j<n; j++)
	if (goods[i].gv<goods[j].gv)
	{
		t = goods[i];
		goods[i] = goods[j];
		goods[j] = t;
	}
}

GBOX *packingbox(GOODS *goods, int n,int s)  
{
	int i;
	GBOX *hb = NULL, *ht=NULL, *p=NULL;
	GNODE *newg, *q;
	for (i = 0; i < n; i++)
	{
		newg = new GNODE;
		newg->gnum = goods[i].go;
		newg->link = NULL;

		for (p = hb; p && p->reminder < goods[i].gv; p = p->next); 

		if (!p)
		{
			p = new GBOX;
			p->head = NULL;
			p->next = NULL;
			p->reminder = s;

			if (!hb)
				hb = ht = p;
			else
				ht = ht->next = p;
		}

		p->reminder -= goods[i].gv;
		for (q = p->head; q&&q->link; q = q->link);// 特别注意  
		if (!q)
			p->head = newg;
		else
			q->link = newg;
	}
	return hb;
}

void   printpackingbox(GBOX *hbox)   //输出   
{
	GBOX *p;
	GNODE *q;
	int i = 0;
	for (p = hbox; p; p = p->next)
	{
		i++;
		cout << "这是第" << i << "个箱子,里面有";
		for (q = p->head; q; q = q->link)
		{
			cout << "编号为" << q->gnum<< "的物品"<<' ';
		}
		cout <<endl;
	}
}

int main()
{
	int n,s;
	GOODS *goods;
	GBOX *hbox;
	cout << "请你输入物品的个数: ";
	cin >> n;
	cout << "请输入一个箱子装多大的体积: ";
	cin >> s;
	goods = new GOODS;
	for (int i = 0; i<n; i++){
		cout << "输入第" << i + 1 << "个物品的体积是";
		cin >> goods[i].gv;
		goods[i].go = i + 1;

	}
	sort(goods, n);
	hbox = packingbox(goods, n,s);  //箱子的头结点   
	printpackingbox(hbox);   //输出   
	return 0;
}

运行结果:

在这里插入图片描述

有兴趣可以加群一起讨论:948097478
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值