算法设计与分析实验代码

实验一 分治法求众数问题(或…)

#include <iostream> 
#include <vector>   
#include <map>      
using namespace std;
 
// 定义一个函数,用于查找给定数组的众数   分治法
int findMode(const vector<int>& nums, int left, int right) {
    // 如果左边界等于右边界,说明只有一个元素,直接返回该元素作为众数
    if (left == right) {
        return nums[left];
    }
 
    // 计算中间位置
    int mid = left + (right - left) / 2;
    // 递归查找左半部分的众数
    int leftMode = findMode(nums, left, mid);
    // 递归查找右半部分的众数
    int rightMode = findMode(nums, mid + 1, right);
 
    // 创建一个映射count,用于统计每个元素出现的次数
    map<int, int> count;
    //通过遍历数组中的元素,将每个元素作为键,出现次数作为值,存储到映射中。
    for (int i = left; i <= right; ++i) {
        count[nums[i]]++;
    }
 
    // 获取左半部分众数的出现次数
    int leftCount = count[leftMode];
    // 获取右半部分众数的出现次数
    int rightCount = count[rightMode];
 
    // 根据出现次数比较左右两部分的众数,返回出现次数较多的那个
    if (leftCount > rightCount) {
        return leftMode;
    }
    else if (leftCount < rightCount) {
        return rightMode;
    }
    else {
        // 如果左右两部分众数出现次数相同,则返回较大的那个
        return max(leftMode, rightMode);
    }
}
 
int main() {
    // 定义一个包含重复元素的数组
    vector<int> nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 1, 2, 2, 3, 3, 3, 3 };
    // 调用findMode函数查找众数,并将结果存储在变量mode中
    int mode = findMode(nums, 0, nums.size() - 1);
    cout << "{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 1, 2, 2, 3, 3, 3, 3 }的众数是: " << mode << endl;
    return 0;
}
 
 
/*这段代码实现了一个名为findMode的函数,它接受一个整数类型的向量nums和两个整数类型的参数left和right,表示要查找的数组范围。
  函数的目的是找到给定数组中的众数并返回。
  首先,函数检查左边界是否等于右边界,如果是,则说明只有一个元素,直接返回该元素作为众数。
  否则,函数会计算中间位置mid,然后递归地在左半部分和右半部分分别查找众数。
  这是通过调用findMode函数实现的,传入左边界、中间位置加一和右边界作为参数。
  接下来,函数创建一个映射count,用于统计每个元素出现的次数。
  通过遍历数组中的元素,将每个元素作为键,出现次数作为值,存储到映射中。
  然后,函数获取左半部分众数leftMode和右半部分众数rightMode的出现次数。
  通过查询映射count,可以获取这两个众数的出现次数。
  最后,函数根据出现次数比较左右两部分的众数。如果左半部分众数的出现次数大于右半部分众数的出现次数,则返回左半部分众数;
  如果左半部分众数的出现次数小于右半部分众数的出现次数,则返回右半部分众数;
  如果左右两部分众数出现次数相同,则返回较大的那个。这是通过使用条件语句和比较运算符来实现的。
  在main函数中,定义了一个包含重复元素的数组nums,然后调用findMode函数来查找众数,并将结果存储在变量mode中。
  最后,输出众数的值。*/
#include <iostream>
#include <vector>
 
using namespace std;
 
// 分治求解函数
int findElement(const vector<int>& arr, int left, int right, int i) {
    if (left > right) {
        return -1; // 未找到元素,返回-1
    }
 
    int mid = left + (right - left) / 2;
 
    if (arr[mid] == i) {
        return arr[mid]; // 找到元素,返回该元素
    }
    else if (arr[mid] > i) {
        return findElement(arr, left, mid - 1, i); // 在左半部分继续查找
    }
    else {
        return findElement(arr, mid + 1, right, i); // 在右半部分继续查找
    }
}
 
int main() {
    vector<int> arr = { 1, 3, 5, 7, 9 };
    int i = 5;
 
    int result = findElement(arr, 0, arr.size() - 1, i);
    if (result != -1) {
        cout << "元素 " << i << " 在有序序列中的位置为: " << result << endl;
    }
    else {
        cout << "元素 " << i << " 不在有序序列中" << endl;
    }
 
    return 0;
}

实验二 动态规划法求单源最短路径问题

#include <iostream> 
#include <vector>   
#include <climits>  
using namespace std; 
 
// 定义图的边结构,包含目标节点和权重
struct Edge 
{
    int dest, weight;
};
 
// 定义图的结构,包含节点数 V 和邻接列表 adjList
struct Graph 
{
    int V;
    vector<vector<Edge>> adjList;
};
 
// 递归和动态规划求解最短路径
int dp(const Graph& graph, int src, int dest, vector<vector<int>>& memo)  //vector<vector<int>>& memo:表示一个二维向量,用于存储已经计算过的子问题的解。这样可以避免重复计算,提高算法的效率。
{
    if (src == dest) 
    { // 如果源节点等于目标节点,说明已经到达目的地,距离为0
        return 0;
    }
 
    // 如果已经计算过从src到dest的最短路径,直接返回memo中的结果
    if (memo[src][dest] != -1) 
    {
        return memo[src][dest];
    }
 
    int minDistance = INT_MAX; // 初始化最小距离为整数极限,用于初始化最短距离和判断是否存在路径。
 
    // 遍历源节点的邻接列表
    for (const Edge& edge : graph.adjList[src]) 
    {
        int nextNode = edge.dest; // 获取下一个节点
        int weight = edge.weight; // 获取边的权重
 
        // 递归计算从nextNode到dest的最短路径
        int distance = dp(graph, nextNode, dest, memo);
 
        // 更新最短路径
        if (distance != INT_MAX) 
        {
            minDistance = min(minDistance, weight + distance);
        }
    }
 
    // 将计算结果保存在memo中
    memo[src][dest] = minDistance;
 
    return minDistance; // 返回最短路径
}
 
// 主函数
int main() {
    Graph graph = { // 定义图的结构
        10, // 节点数为10
        { // 邻接列表
            {{1, 4}, {2, 2}, {3, 3}}, 
            {{4, 9}, {5, 8}}, 
            {{4, 6}, {5, 7}, {6, 8}}, 
            {{5, 4}, {6, 7}}, 
            {{7, 5}, {8, 6}}, 
            {{7, 8}, {8, 6}}, 
            {{7, 6}, {8, 5}}, 
            {{9, 7}}, 
            {{9, 3}}, 
            {} 
        }
    };
    int src = 0, dest = 9; // 定义源节点和目标节点
 
    // 初始化memo数组,创建了一个大小为 graph.V 行、graph.V 列的二维向量,并将所有元素初始化为 -1。
    vector<vector<int>> memo(graph.V, vector<int>(graph.V, -1));
 
    // 调用dp函数求解最短路径
    int shortestPath = dp(graph, src, dest, memo);
 
    // 输出最短路径
    if (shortestPath == INT_MAX) 
    {
        cout << "从源节点 " << src << " 到节点 " << dest << " 不存在路径。" << endl;
    }
    else 
    {
        cout << "从源节点 " << src << " 到节点 " << dest << " 的最短距离为 " << shortestPath << endl;
    }
 
    return 0;
}
 
/*
首先,定义了两个结构体,Edge和Graph。Edge表示图的边,包含目标节点和权重;Graph表示图的结构,包含节点数V和邻接列表adjList。
然后,实现了一个名为dp的递归函数,用于求解从源节点到目标节点的最短路径。
该函数接受四个参数:图graph、源节点src、目标节点dest和一个二维向量memo。memo用于存储已经计算过的子问题的解,避免重复计算。
在dp函数中,首先判断源节点是否等于目标节点,如果是,则说明已经到达目的地,距离为0,直接返回0。
如果已经计算过从源节点到目标节点的最短路径,则直接从memo中返回结果。
接下来,初始化最小距离minDistance为整数极限INT_MAX,用于初始化最短距离和判断是否存在路径。
遍历源节点的邻接列表,对于每个邻接节点,获取下一个节点nextNode和边的权重weight。
递归调用dp函数,计算从nextNode到目标节点的最短路径distance。
如果distance不等于INT_MAX,说明存在从nextNode到目标节点的路径,更新最小距离minDistance为当前最小距离和weight+distance中的较小值。
将计算结果保存在memo中,以便后续使用。
最后,返回最小距离minDistance作为从源节点到目标节点的最短路径。
在主函数中,定义了一个图graph,包含了节点数V和邻接列表adjList。然后定义了源节点src和目标节点dest。
初始化memo数组,创建了一个大小为graph.V行、graph.V列的二维向量,并将所有元素初始化为-1。
调用dp函数求解最短路径,并将结果保存在shortestPath变量中。
根据shortestPath的值判断是否存在路径,如果等于INT_MAX,则输出不存在路径的信息;否则,输出最短路径的结果。
*/

实验三 贪心法求汽车加油问题

#include <iostream>
using namespace std;
 
int n = 30;//加满油后可行驶的距离
const int m = 10;  //加油站个数
int A[m] = { 10,15,10,17,8,17,13,9,11,10 };//加油站距离(为i-1与i之间的距离)
int main() {
    int s = n;//当前剩余油量可行驶距离
    int flag[m] = { 0,0,0,0,0,0,0,0,0,0 };//记录加油站索引
    int k = 0;//加油站个数记录
    for (int i = 0; i < m; i++)
    {
        if (n < A[i])
        {
            cout << "no solution!" << endl;
            break;
        }
        if (s - A[i] >= 0)
        {
            s -= A[i];
        }
        else
        {
            s = n - A[i];
            flag[k++] = i - 1;
        }
    }
    int a = 0;
    cout << "the need stations are:" << endl;
    while (flag[a] != 0)
        cout << flag[a++] << ",";
    return 0;
}

实验四 回溯法求0/1背包问题

#include<iostream>
#include<stack>//使用栈(后进先出)
using namespace std;
 
int maxValue(int w[], int v[], const unsigned& length, const unsigned& capacity)
{
    stack<int> Bag;//首先构造出一个空的背包
    int max = 0;//不同装入情况中背包中物品最大的价值
    int weight = 0;//当前背包中物品的总重量
    int value = 0;//当前背包中物品的总价值
    int i;
 
    for (i = 0; ; i++)
    {
        if (weight + w[i] <= capacity)//背包装入该物品后不会超重
        {
            Bag.push(i);//入栈
            weight += w[i];
            value += v[i];
        }
        if (i == length - 1)
        {
            //接下来将本次装包物品价值与当前最高的装包物品价值进行比较,保留较大的一个
            if (max < value)
            {
                max = value;
            }
            //此时取出最后装进包里的一件物品并对其下一件物品进行考虑——回溯法核心
            {
                i = Bag.top();//取出上一件装入的东西(回溯的过程)
                Bag.pop();
                weight -= w[i];
                value -= v[i];
                if (i == length - 1)//特殊情况:如果最后装进包里的物品本来在就是编号最大的物品,那么它后面就没有其他物品了,循环必定终止
                {
                    if (Bag.empty())break;//当所有物品都被从包中拿出来后,这是说明已经遍历完所有情况,查找结束(相当于解空间树中最右边的子树已经走完了)
                    i = Bag.top();//取出上一件装入的东西,这就是回溯的过程
                    Bag.pop();
                    weight -= w[i];
                    value -= v[i];
                }
            }
        }
    }
    return max;
}
 
int main()
{
    unsigned num, capacity;
    cout << "please enter the number of items:";
    cin >> num;
    int* weights = new int[num];
    int* values = new int[num];
    cout << "please enter the weight of each item:";
    for (unsigned i = 0; i < num; i++)
    {
        cin >> weights[i];
    }
    cout << "please enter the value of each item:";
    for (unsigned i = 0; i < num; i++)
    {
        cin >> values[i];
    }
    cout << "please enter the capacity of the bag:";
    cin >> capacity;
    cout << "the optimal solution to this problem of Backtracking is:" << maxValue(weights, values, num, capacity);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值