大家如果对算法导论以及其他信息感兴趣,可以加入学习交流群一起交流 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