本文章仅转载他人代码,非本人实验所用!如有侵权,请联系我,我会删除文章!
请同学们自主思考,不要复制粘贴网上代码,不当使用造成的后果本人概不负责!
实验任务书
本文章是我整合了两个人的实验所完成,其中部分代码是他们从网上粘贴然后自己进行修改,为了降重把一些变量名和函数名改的非常反人类,如有雷同,不是巧合。
实验一 归并排序
2024.2.2补充:copy那块多打了几个大括号,缩进有点问题,但是不影响执行。
#include<iostream>
#include<vector>
#include<ctime>
#include <random>
#include<algorithm>
using namespace std;
float a[1000000]{ };//生成一百万个随机数
float c[1000000]{};
float d[1000000]{};
template <class T>
bool operator <(const T& a, const T& b) {
return (a.data < b.data);
}
template <class T>
void merge_sort(T a[], int l, int r)
{
if (l == r)
return;
int mid = l + r >> 1;
merge_sort(a, l, mid), merge_sort(a, mid + 1, r);
int i = l, j = mid + 1, k = 0;
while (i <= mid && j <= r) {
if (a[i] <= a[j]) {
c[k++] = a[i++];
}
else {
c[k++] = a[j++];
}
}
while (i <= mid) c[k++] = a[i++]; {
while (j <= r) c[k++] = a[j++]; {
for (int i = l, j = 0; i <= r; i++, j++) {//Copy
a[i] = c[j];
}
}}
}
int main()
{
time_t begin1, end1,begin2,end2;
uniform_real_distribution<double> u(-20030905, 20030905);
default_random_engine e(time(NULL));
ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);//阻止科学计数法
std::streamsize prec = cout.precision(5);//控制位数
//归并排序开始计时
for (int i = 0; i < 1000000; i++) {
a[i] = u(e);
d[i] = a[i];
}
begin1 = clock();
merge_sort(a, 0, 999999);
/*for (int i = 0; i < 100; i++) {
printf("%8f ", a[i]);
}*/
end1 = clock();
double time1 = (double)(end1 - begin1) / CLOCKS_PER_SEC;
cout << endl;
cout <<"归并排序的时间为 " << time1<<"s";
begin2 = clock();
sort(d, d + 1000001);
end2 = clock();
double time2 = (double)(end2 - begin2) / CLOCKS_PER_SEC;
cout << endl;
cout << "标准库排序的时间为 " << time2 << "s" << endl;
}
其实没用到vector,当时是考虑输入的数据类型可能不是数字才设置的,mid右移一位是因为我当时学的那篇文章就用的位运算,我索性直接复制过来了,其实就是除以二。
2024.2.3补充:加一个非递归实现归并排序,排序之归并排序-CSDN博客,f是待排数组,g是存放临时数据的数组。
void no_merge_sort(float f[], int n) {
int gap = 1;
while (gap < n) {
for (int i = 0; i < n; i += gap * 2) {
int begin1 = i;
int end1 = i + gap-1;
int begin2 = end1 + 1;
int end2 = i + 2 * gap - 1;
if (end1 >= n || begin2 >= n) {
break;
}
if (end2 >= n) {
end2 = n - 1;
}
int j = begin1;
while ((begin1 <= end1) && (begin2 <= end2))
{
if (f[begin1] < f[begin2])
{
g[j++] = f[begin1++];
}
else
{
g[j++] = f[begin2++];
}
}
while (begin1 <= end1)
{
g[j++] = f[begin1++];
}
while (begin2 <= end2)
{
g[j++] = f[begin2++];
}
}
gap = gap * 2;
}
for (int k = 0; k < 1000000; k++) {
f[k] = g[k];
}
}
实验二 哈夫曼编码
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct THuffman {
char ch;
long weight;
int l, r;
int p;
string code;
int idx;//记录索引,便于建立树
THuffman() :l(-1), r(-1), p(-1), ch('/0'), weight(0), idx(-1) {}
};
struct temp_node {
char ch = '0';
long weight = 0;
};
bool operator >(const THuffman& a, const THuffman& b) {
return(a.weight > b.weight);
}
bool operator <(const THuffman& a, const THuffman& b) {
return(a.weight < b.weight);
}
struct Huffman {
string hfilename;
Huffman(string filename) {
hfilename = filename;
}
void OutputCode() {
unsigned char temp_char;
long file_len = 0;//统计文件长度
int kind = 0;
temp_node filechar[256];//此数组装载文件中字符频度及字符本身
for (int i = 0; i < 256; i++) {
filechar[i].weight = 0;
filechar[i].ch = (unsigned char)i;
}
ifstream infile;
infile.open(hfilename);
if (!infile.is_open()) {
cout << "打开文件失败";
return ;
}
infile.read((char*)&temp_char, sizeof(unsigned char));
while (!infile.eof()) {//这么写可以防止文件里什么也没有导致filechar中数据出错
filechar[temp_char].weight++;
file_len++;
infile.read((char*)&temp_char, sizeof(unsigned char));
}
infile.close();
//接下来排序,以便获得文件中字符数目
sort(filechar, filechar + 257, [](temp_node a, temp_node b) {
return a.weight > b.weight; });
for (int i = 0; i < 256; i++) {
if (filechar[i].weight != 0) {
kind++;
}
}
//文件信息已扫描完毕,可以开始进行编码了
THuffman* t = new THuffman[2 * kind - 1];
priority_queue<THuffman, vector<THuffman>, greater<THuffman>>PQ;
for (int i = 0; i < kind; i++) {
t[i].idx = i;
t[i].weight = filechar[i].weight;
t[i].ch = filechar[i].ch;
PQ.push(t[i]);
}
int k = kind;
for (int i = 0; i <= kind - 2; i++) {
THuffman l = PQ.top();
PQ.pop();
THuffman r = PQ.top();
PQ.pop();
t[k].idx = k;
t[k].weight = l.weight + r.weight;
t[k].l = l.idx;
t[k].r = r.idx;
t[l.idx].p = k;
t[r.idx].p = k;
PQ.push(t[k]);
k++;
}
//树已经得到,接下来输出各编码
priority_queue<THuffman, vector<THuffman>>output;
for (int i = 0; i < kind; i++) {
output.push(t[i]);
}
for (int i = 0; i < kind; i++) {
cout << output.top().ch << ":" << output.top().weight << "次,编码为";
THuffman p = output.top();
THuffman pp = t[p.p];
stack<int>code;
while (1) {
if (p.idx == pp.l) {
code.push(0);
}
else if (p.idx == pp.r) {
code.push(1);
}
p = pp;
if (p.p == -1) {
break;
}
pp = t[p.p];
}
int temp = code.size();
for (int j = 0; j < temp; j++) {
cout << code.top();
//t[output.top().idx].code += code.top();
code.pop();
}
cout << endl;
output.pop();
}
delete[]t;
}
};
int main() {
Huffman hm("test.txt");
cout << "打开的文件名为:test.txt" << endl;
hm.OutputCode();
}
运行结果类似这样
待打开的文件放在visual对应的文件夹下面运行,其实这个代码打不开doc文件,但是txt文件自己把后缀改成doc之后就可以,我也不知道为什么;老师建议不要用逐字符的方式读入,可以改成一次读入若干字符提高效率,这里没改,请读者自行发挥吧。
实验三 矩阵链乘
#include <iostream>
#include <string>
using namespace std;
struct Sheet {
long m;
int k;
};
struct matrix {
int right_right_bak = 0;
int left_left_bak = 0;
int right_left_bak = 0;
string ch;
};
int p[] = { 60,2,1,3,4,5,2};
int n = 6;
Sheet** A = new Sheet * [n + 1];
void bracket2(int left, int right, matrix* a)
{
if (left == right)
{
cout << a[left].ch;
}
else
{
cout<<"(";
bracket2(left, A[left][right].k,a);
bracket2(A[left][right].k + 1, right,a);
cout<<")";
}
}
int main()
{
for (int i = 0; i <= n; i++) {
A[i] = new Sheet [n + 1];
A[0][i].m = 0;
}
for (int i = 0; i <= n; i++) {
A[i][i].m = 0;
A[i][i].k = 0;
}
A[1][2].m = p[0] * p[1] * p[2];
for (int r = 2; r <= n; r++) {
for (int i = 1; i + r - 1 <= n; i++) {
int j = r + i - 1;
long mm = A[i + 1][j].m + p[i - 1] * p[i] * p[j];
int kk = i;
for (int k = i + 1; k < j; k++) {
long tempM = A[i][k].m + A[k + 1][j].m + p[i - 1] * p[k] * p[j];
if (tempM < mm) {
mm = tempM;
kk = k;
}
}
A[i][j].m = mm;
A[i][j].k = kk;
}
}
matrix a[27];
a[0].ch = "NULL";
a[1].ch = "A";
a[2].ch = "B";
a[3].ch = "C";
a[4].ch = "D";
a[5].ch = "E";
a[6].ch = "F";
a[7].ch = "G";
a[8].ch = "H";
a[9].ch = "I";
a[10].ch = "J";
a[11].ch = "K";
a[12].ch = "L";
a[13].ch = "M";
a[14].ch = "N";
a[15].ch = "O";
a[16].ch = "P";
a[17].ch = "Q";
a[18].ch = "R";
a[19].ch = "S";
a[20].ch = "T";
a[21].ch = "U";
a[22].ch = "V";
a[23].ch = "W";
a[24].ch = "X";
a[25].ch = "Y";
a[26].ch = "Z";
cout<<"最小乘法次数为 " << A[1][n].m << endl;
cout << "加括号方式为";
bracket2(1, n, a);
for (int i = 0; i <= n; i++) {
delete []A[i];
}
delete[]A;
}
其实我自己花好久写了一个加括号方式,但是运行结果太丑了,无奈删掉( Ĭ ^ Ĭ )。
没有输入,自己修改矩阵数量和行列数,行列数数组第0个元素是第一个矩阵的行,第i个元素是第i个矩阵的列数。
结果大概这样
实验四 n皇后问题
#include <iostream>
#include <vector>
using namespace std;
struct Queen {
int N;
int m_sum;//解数
Queen() {};
~Queen() {};
vector<int> row_set;//每一行皇后的置放位置情况
vector<int> col_set;//每一列只能有一个皇后,记录每一列的状态
vector<vector<int>> solution;//存储可行方案
int curRow = 0;//当前待放皇后的行数
bool check(int curRow, int col) {
for (int i = curRow - 1; i >= 0; i--) {
if (curRow - i == abs(col - row_set[i])) {
return false;
}
}
return true;
}
void Slove(int curRow) {
if (curRow >= N) {//递归出口
solution.push_back(row_set);
return;
}
for (int i = 0; i < N; ++i) {
if (col_set[i]) {
continue;
}
if (check(curRow, i)) {
col_set[i] = true;
row_set.push_back(i);
Slove(curRow + 1);
col_set[i] = false;
row_set.pop_back();
}
}
}
void IniQueen(int n) {//初始化,并计算该n值下的各种解
N = n;
for (int i = 0; i < N; i++) {
col_set.push_back(0);
}
Slove(0);
}
void Print_All() {//输出n皇后问题的所有解向量
int f = 1;
cout << N << "皇后问题,方案如下:" << endl<<endl;
for (vector<vector<int>>::iterator it = solution.begin(); it != solution.end(); it++) {
cout << "第" << f++ << "种放置方案, 解向量为 " << endl;
for (int i = 0; i < it->size(); i++) {
cout << (*it)[i] + 1 << " ";
}
cout << endl;
}
return;
}
int Get_Key_Sum() {//返回解数
m_sum = solution.size();
return m_sum;
}
void Print_Firstkey() {//输出第一个解向量
cout << "(";
for (int i = 0; i < solution[0].size()-1; i++) {
cout << solution[0][i]+1 << " ,";
}
cout << solution[0][solution[0].size() - 1]+1;
cout << ")";
return;
}
void Print_Sheet() {//输出表格
char h_line = '-';
char v_line = '|';
for (int i = 0; i < 67; i++) {
cout << h_line;
}
cout << endl;
cout << " 皇后数 ";
cout << v_line;
cout << " 解数 ";
cout << v_line;
cout << " 第一个解 ";
cout << v_line;
cout << endl;
for (int i = 4; i <= N; i++) {
for (int i = 0; i < 67; i++) {
cout << h_line;
}
cout << endl;
Queen temp;
temp.IniQueen(i);
printf("%5d", i);
cout << " ";
cout << v_line;
printf("%6d", temp.Get_Key_Sum());
cout << " ";
cout << v_line;
temp.Print_Firstkey();
cout << endl;
}
}
};
int main() {
Queen que;
que.IniQueen(6);
que.Print_Sheet();
que.Print_All();
}
运行时自己修改初始化时的参数,皇后数尽量不要超过12,要不然会很慢。准备了好几个输出用的函数,用哪个调哪个。
实验五 贪心背包
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
using namespace std;
/*实验要求为贪心算法,本题为部分背包问题,每种物品只有一个,但是可以取部分,
考虑到本实验要求std::sort,所以没有使用优先队列,而是使用vector*/
struct goods {
float value = 0.0;
float weight = 0.0;
float rate = 0.0;
bool pick = false;
int number = 0;
goods() {};
goods(float v, float w) {
value = v;
weight = w;
rate = value / weight;
}
void cum_rate() {
rate = value / weight;
}
};
bool cmp_rate(const goods a, const goods b) {
return (a.rate > b.rate);
}
bool cmp_number(const goods a, const goods b) {
return (a.number < b.number);
}
struct Greedy_partbag {
int n;//待选物品数量
float c=0.0;//背包容量
float cv=0.0;//已经装入的价值
float cw=0.0;//已经装入的重量
vector<goods>goods_set;//所有物品的状态表
Greedy_partbag() {};
~Greedy_partbag() {};
void Greedy_partbag_Solution() {//读取输入并解决问题
cin >> n;
cin >> c;
uniform_real_distribution<float> u(0, 100);
default_random_engine e(time(0));
for (int i = 0; i < n; i++) {//读取输入
goods temp;
/*cin >> temp.value;
cin >> temp.weight;*/
//这里采用随机数的方法作为价值和重量
temp.value = u(e);
temp.weight = u(e);
temp.rate = temp.value / temp.weight;
temp.number = i + 1;
goods_set.push_back(temp);
}
//接下来对物品性价比进行排序
sort(goods_set.begin(), goods_set.end(), cmp_rate);
for (int i = 0; i < n; i++) {//装入物品
if (goods_set[i].weight < (c - cw)) {
goods_set[i].pick = true;
cv = cv + goods_set[i].value;
cw = cw + goods_set[i].weight;
continue;
}
if (goods_set[i].weight == (c - cw)) {
goods_set[i].pick = true;
cv = cv + goods_set[i].value;
cw = cw + goods_set[i].weight;
break;
}
if (goods_set[i].weight > (c - cw)) {
goods_set[i].pick = true;
cv = cv + goods_set[i].value*((c-cw)/goods_set[i].weight);
cw = c;
break;
}
}
//重新排序,以便于输出物品列表
sort(goods_set.begin(), goods_set.end(), cmp_number);
}
void Print_Sheet() {
for (int i = 1; i <= goods_set.size() + 1; i++) {
cout << "--------" ;
}
cout << "-";
cout << endl;
cout << "物品编号" << "|";
for(int i=1;i<=goods_set.size();i++){
printf("%4d", i);
cout << " |";
}
cout << endl;
for (int i = 1; i <= goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
cout << " 重量 "<<"|";
for (int i = 0; i < goods_set.size(); i++) {
printf("%5.1f", goods_set[i].weight);
cout << " |";
}
cout << endl;
for (int i = 1; i <= goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
cout << " 价值 " << "|";
for (int i = 0; i < goods_set.size(); i++) {
printf("%5.1f", goods_set[i].value);
cout << " |";
}
cout << endl;
for (int i = 1; i <= goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
cout << "选中状态" << "|";
for (int i = 0; i < goods_set.size(); i++) {
printf("%4d", goods_set[i].pick);
cout << " |";
}
cout << endl;
for (int i = 1; i <= goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
cout << " 性价比 " << "|";
for (int i = 0; i < goods_set.size(); i++) {
printf("%5.2f", goods_set[i].rate);
cout << " |";
}
cout << endl;
for (int i = 1; i <= goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
}
void Print_Result() {
printf("最佳价值为 %.2f",cv);
}
};
int main() {
Greedy_partbag bag;
cout << "输入物品数量和背包容量:" << endl;;
bag.Greedy_partbag_Solution();
bag.Print_Sheet();
bag.Print_Result();
}
实验六 0-1背包
回溯法
#include <iostream>
#include <vector>
#include <random>
using namespace std;
//深搜背包
struct goods {
float value = 0.0;
float weight = 0.0;
int number = 0;
bool pick = false;
};
struct dfs_bag {
int n = 0;
float c = 0.0;
float cv = 0.0;
float cw = 0.0;
float max_v = 0.0;
int* best;
vector<goods>goods_set;
dfs_bag() {};
~dfs_bag() {
delete[]best;
};
void input() {
cin >> n;
cin >> c;
best = new int [n+1];
for (int i = 0; i <= n; i++)
best[i] = 0;
uniform_real_distribution<float> u(0, 100);
default_random_engine e(time(0));
goods scrap;//第一个元素无效,为了对齐编号加的
goods_set.push_back(scrap);
for (int i = 0; i < n; i++) {//读取输入
goods temp;
/*cin >> temp.value;
cin >> temp.weight;*/
temp.value = u(e);
temp.weight = u(e);
temp.number = i + 1;
goods_set.push_back(temp);
}
}
void dfs(int k) {
if (k > n) {
if (cv > max_v) {
max_v = cv;
for (int i = 1; i <= n; i++) {
best[i] = goods_set[i].pick;
}
return;
}
return;
}
for (int i = 1; i >= 0; i--) {//轮流赋1或0表示选中与否
goods_set[k].pick = i;
if (cw + goods_set[k].pick * goods_set[k].weight <= c) {
cw = cw + goods_set[k].pick * goods_set[k].weight;
cv = cv + goods_set[k].pick * goods_set[k].value;
dfs(k + 1);
cw = cw - goods_set[k].pick * goods_set[k].weight;
cv = cv - goods_set[k].pick * goods_set[k].value;//解已经存入数组,把cv和cw还原便于其他递归调用
}
}
}
void Print_Sheet() {
for (int i = 1; i < goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-";
cout << endl;
cout << "物品编号" << "|";
for (int i = 1; i < goods_set.size(); i++) {
printf("%4d", i);
cout << " |";
}
cout << endl;
for (int i = 1; i < goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
cout << " 重量 " << "|";
for (int i = 1; i < goods_set.size(); i++) {
printf("%5.1f", goods_set[i].weight);
cout << " |";
}
cout << endl;
for (int i = 1; i <= goods_set.size(); i++) {
cout << "--------";
}
cout << "-" << endl;
cout << " 价值 " << "|";
for (int i = 1; i < goods_set.size(); i++) {
printf("%5.1f", goods_set[i].value);
cout << " |";
}
cout << endl;
for (int i = 1; i <= goods_set.size(); i++) {
cout << "--------";
}
cout << "-" << endl;
cout << "选中状态" << "|";
for (int i = 1; i < goods_set.size(); i++) {
printf("%4d", best[i]);
cout << " |";
}
cout << endl;
for (int i = 1; i < goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
}
void Print_Result() {
printf("最佳价值为 %.2f", max_v);
}
};
int main() {
dfs_bag a;
a.input();
a.dfs(1);
a.Print_Sheet();
a.Print_Result();
}
输入为 物品数量和背包容量。
分支限界
#include <iostream>
#include <vector>
#include<algorithm>
#include<queue>
#include <random>
using namespace std;
struct goods
{
int number;
float weight;
float value;
float d;
};
struct Big_Priority_Tree
{
Big_Priority_Tree* parent;
int lchild;
float upvalue;
float value;
float weight;
int layer;
};
struct cmp
{
bool operator()(Big_Priority_Tree*& a, Big_Priority_Tree*& b) const
{
return a->upvalue < b->upvalue;
}
};
bool compare(const goods a, const goods b)
{
return a.d >= b.d;
}
int n;
float c;
float cw;
float cv;
float max_v;
vector<goods> goods_set;
vector <goods>origin_goods_set;
int bestx[100];
void input()
{
cin >> n >> c;
uniform_real_distribution<float> u(0, 100);
default_random_engine e(time(0));
for (int i = 1; i <= n; i++)
{
goods temp;
temp.value = u(e);
temp.weight = u(e);
temp.number = i;
temp.d = 1.0 * temp.value / temp.weight;
goods_set.push_back(temp);
}
origin_goods_set = goods_set;
sort(goods_set.begin(), goods_set.end(), compare);
}
float Bound(int i)
{
float tmp_cleft = c - cw;
float tmp_cv = cv;
while (i<=n&&tmp_cleft >= goods_set[i-1].weight )
{
tmp_cleft -= goods_set[i-1].weight;
tmp_cv += goods_set[i-1].value;
i++;
}
if (i <= n)
{
tmp_cv += tmp_cleft * goods_set[i-1].d;
}
return tmp_cv;
}
void Push_Alive_Node(priority_queue<Big_Priority_Tree*, vector<Big_Priority_Tree*>, cmp>& q, Big_Priority_Tree* E, float up, float wt, float curp, int i, int ch)
{
Big_Priority_Tree* p = new Big_Priority_Tree;
p->parent = E;
p->lchild = ch;
p->weight = wt;
p->upvalue = up;
p->value = curp;
p->layer = i + 1;
q.push(p);
}
void Bag()
{
priority_queue<Big_Priority_Tree*, vector<Big_Priority_Tree*>, cmp > q;
Big_Priority_Tree* E = NULL;
cw = cv = max_v = 0;
int i = 1;
float up = Bound(1);
while (i != n + 1)
{
float wt = cw + goods_set[i-1].weight;
if (wt <= c)
{
if (max_v < cv + goods_set[i-1].value)
max_v = cv + goods_set[i-1].value;
Push_Alive_Node(q, E, up, cw + goods_set[i-1].weight, cv + goods_set[i-1].value, i, 1);
}
up = Bound(i + 1);
if (up >= max_v)
{
Push_Alive_Node(q, E, up, cw, cv, i, 0);
}
E = q.top();
q.pop();
cw = E->weight;
cv = E->value;
up = E->upvalue;
i = E->layer;
}
for (int i = 0; i<n; i++)
{
bestx[goods_set[E->layer - 2].number] = E->lchild;
E = E->parent;
}
}
void Print_Sheet() {
for (int i = 0; i < goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-";
cout << endl;
cout << "物品编号" << "|";
for (int i = 1; i <= goods_set.size(); i++) {
printf("%4d", i);
cout << " |";
}
cout << endl;
for (int i = 0; i < goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
cout << " 重量 " << "|";
for (int i = 0; i < goods_set.size(); i++) {
printf("%5.1f", origin_goods_set[i].weight);
cout << " |";
}
cout << endl;
for (int i = 0; i <= goods_set.size(); i++) {
cout << "--------";
}
cout << "-" << endl;
cout << " 价值 " << "|";
for (int i = 0; i < goods_set.size(); i++) {
printf("%5.1f", origin_goods_set[i].value);
cout << " |";
}
cout << endl;
for (int i = 0; i <= goods_set.size(); i++) {
cout << "--------";
}
cout << "-" << endl;
cout << "选中状态" << "|";
for (int i = 1; i <= goods_set.size(); i++) {
printf("%4d", bestx[i]);
cout << " |";
}
cout << endl;
for (int i = 0; i < goods_set.size() + 1; i++) {
cout << "--------";
}
cout << "-" << endl;
}
void Print_Max_v()
{
printf("最优装入量为 %.2f", max_v);
cout << endl;
}
int main()
{
input();
Bag();
Print_Max_v();
Print_Sheet();
}
代码是网上搜的,建议大家也去搜索然后认真学习一下,分支限界并不是单纯的广搜,而是使用优先队列和限界函数进行辅助,
实验七 第K小问题
原地分区
#include <iostream>
#include<random>
#include <algorithm>
//原地分区法第k小问题
using namespace std;
inline void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int partition(int a[], int l, int r) {
int x = a[l];
int i = l;
for (int j = l + 1; j <= r; j++) {
if (a[j] < x) {
i++;
swap(a[i], a[j]);
}
}
swap(a[i], a[l]);
return i;
}
int kth_element_partition(int* a, int l, int r, int k) {
if (l == r) {
return a[l];
}
int m = partition(a, l, r);
int kk = m - l + 1;
if (k == kk) {
return a[m];
}
if (k < kk) {
return kth_element_partition(a, l, m - 1, k);
}
else return kth_element_partition(a, m + 1, r, k - kk);
}
int main()
{
int n = 0;
int k = 0;
int a[10]{};
uniform_real_distribution<float> u(0, 100);
default_random_engine e(time(NULL));
for (int i = 0; i < sizeof(a) / sizeof(int); i++) {
a[i] = (int)u(e);
}
cin >>k;
for (int i = 0; i < sizeof(a) / sizeof(int); i++) {
cout << a[i]<<" ";
}
cout << endl;
cout << kth_element_partition(a, 0, sizeof(a)/sizeof(int)-1, k)<<endl;
}
线性时间选择
#include<iostream>
#include<vector>
#include <algorithm>
#include <random>
using namespace std;
int n, k;
vector<int>vec;
int partition(vector<int>& a, int s, int e, int hub) {
int i = s, j = e;
while (i <= e && j >= s) {
while (a[i] < hub)i++;
while (a[j] > hub)j--;
if (i >= j) {
break;
}
else {
swap(a[i], a[j]);
}
}
return j;
}
void Sort(vector<int>& a, int s, int e)
{
for (int i = s; i < e; i++) {
int min = i;
for (int j = i + 1; j < e; j++)
if (a[j] < a[min])
min = j;
swap(vec[i], vec[min]);
}
}
int Mid_kth_Smaller(vector<int>& a, int s, int e, int k) {
if (e - s < 5) {
Sort(a, s, e);
return a[s + k - 1];
}
int standard;
for (int i = 0; i <= (e - s - 4) / 5; i++) {
standard = s + i * 5;
if (a[standard] > a[standard + 1])
swap(a[standard], a[standard + 1]);
if (a[standard + 2] > a[standard + 3])
swap(a[standard + 2], a[standard + 3]);
if (a[standard] > a[standard + 2])
{
swap(a[standard], a[standard + 2]);
swap(a[standard + 1], a[standard + 3]);
}
if (a[standard + 1] > a[standard + 4])
{
swap(a[standard + 1], a[standard + 4]);
}
if (a[standard + 1] > a[standard + 2])
{
swap(a[standard + 1], a[standard + 2]);
swap(a[standard + 3], a[standard + 4]);
}
if (a[standard + 2] > a[standard + 4])
{
swap(a[standard + 2], a[standard + 4]);
}
swap(a[standard + 2], a[s + i]);
}
int mid = Mid_kth_Smaller(a, s, s + (e - s - 4) / 5, ((e - s - 4) / 5 + 1) / 2 + 1);
int mid_location = partition(a, s, e - 1, mid);
int mid_rank = mid_location - s + 1;
if (k == mid_rank) {
return a[mid_location];
}
else if (k < mid_rank) {
return Mid_kth_Smaller(a, s, mid_location, k);
}
else {
return Mid_kth_Smaller(a, mid_location + 1, e, k - mid_rank);
}
}
int main()
{
int temp;
cin >> n >> k;
uniform_real_distribution<float> u(0, 100);
default_random_engine e(time(NULL));
for (int i = 0; i < n; i++)
{
temp = (int)u(e);
vec.push_back(temp);
}
for (int i = 0; i < n; i++) {
cout << vec[i] << " ";
}
cout << endl;
cout << Mid_kth_Smaller(vec, 0, n, k) << endl;
}
期末考试出了个写线性时间选择的递归公式,我没写出来( Ĭ ^ Ĭ )。
实验八 最大子段和
#include<iostream>
#include<random>
#include<ctime>
#include<stdlib.h>
#include <random>
using namespace std;
struct maxSubSum{
int* arr;
maxSubSum(){}
~maxSubSum(){
free(arr);
}
void Create_Psg(int n){
uniform_real_distribution<float> u(-90, 100);
default_random_engine e(time(0));
arr = (int*)malloc(sizeof(int) * (n + 2));
cout << "原段为:";
for (int i = 1; i < n; i++){
arr[i] = (int)u(e);
cout << arr[i] <<",";
}
arr[n] = (int)u(e);
cout << arr[n];
cout << endl;
}
void Enumeration(int n){//暴力枚举
int l = 0, r = 0, s = -999999;
for (int i = 1; i <= n; i++)
for (int j = i ; j <= n; j++) {
int sum = 0;
for (int k = i; k <= j; k++) {
sum += arr[k];
}
if (sum > s){
s = sum;
l = i;
r = j;
}
}
cout << "暴力穷举" <<":";
cout << l << "~" << r;
cout << endl << "值为" << s << endl;
}
void Dp(int r)//动态规划
{
int* fa = new int[r + 1];
int* dp = new int[r + 1];
int s = arr[1], rf = 1;
fa[1] = 1;
dp[1] = arr[1];
for (int i = 2; i <= r; i++){
if (dp[i - 1] > 0){
dp[i] = arr[i] + dp[i - 1];
fa[i] = fa[i - 1];
}
else {
dp[i] = arr[i];
fa[i] = i;
}
if (dp[i] > s){
s = dp[i];
rf = i;
}
}
cout << "动态规划" <<":";
cout << fa[rf] << "~" << rf;
cout << endl << "值为" << s << endl;
}
int Divide_and_Conquer(int l, int r, int& fa, int& fb, int f){//分治{
int sum = 0;
if (l == r){
if (arr[l] > 0){
sum = arr[l];
fa = l;
fb = l;
}
else {
sum = 0;
fa = 0;
fb = 0;
}
}
else
{
int mid = (l + r) / 2;
int la = 0, lb = 0, ra = 0, rb = 0, ma = mid + 1, mb = mid;
int lsum = Divide_and_Conquer(l, mid, la, lb, 1);
int rsum = Divide_and_Conquer(mid + 1, r, ra, rb, 1);
int s1 = 0, ls = 0;
for (int i = mid; i >= l; i--) {
ls += arr[i];
if (ls > s1) {
s1 = ls;
ma = i;
}
}
int s2 = 0, rs = 0;
for (int i = mid + 1; i <= r; i++) {
rs += arr[i];
if (rs > s2){
s2 = rs;
mb = i;
}
}
sum = s1 + s2;
fa = ma;
fb = mb;
if (sum < lsum) {
sum = lsum;
fa = la;
fb = lb;
}
if (sum < rsum){
sum = rsum;
fa = ra;
fb = rb;
}
}
if (!f){
cout << "分治法"<<":";
cout << fa << "~" << fb;
cout << endl << "值为" << sum << endl;
}
return sum;
}
};
int main()
{
int n;
cin >> n;
maxSubSum subsegment;
subsegment.Create_Psg(n);
int a, b;
subsegment.Divide_and_Conquer(1, n, a, b, 0);
subsegment.Enumeration(n);
subsegment.Dp(n);
}
懒得拆了,三种方法合在一起了。为了降重把变量名改的挺抽象的,输入为待处理段的长度。
以上就是实验的所有内容了,本人仅负责转载,内容不一定原创!