实验一 分治算法和贪婪法
一、实验目的
- 掌握分治算法的设计思想与分析方法;
- 能够按题目要求编程实现分治算法;
- 理解和掌握贪婪算法的基本思想;
- 使用贪婪算法求解背包问题以及最小花费生成树问题。
二、实验仪器及设备
- 硬件环境:PC机一台
- 软件环境:Windows 11、C语言(Visual C++ 6.0)
三、实验内容
- 采用分治算法求10个实数{ 9,3,6,2,1,8,4,5,7,23 }序列中的最大元素和最小元素,并分析算法的时间复杂度。
- 采用分治算法方法实现快速排序算法。要求:输入数组为{9,4,6,2,5,8,4,5,6,22 };限定数组排序范围;输出显示为递增顺序排序的数组。
- 利用贪婪法求如下背包问题的最优解:n=5,M=100,价值P={20,30,66,40,60},重量为w={10,20,30,40,50}。
1、分治法求最大最小值 #include <stdio.h> #include <stdlib.h> void maxmin(int a[], int *e_max, int *e_min, int low, int high) { if (high - low <= 1) { *e_max = (a[low] > a[high]) ? a[low] : a[high]; *e_min = (a[low] < a[high]) ? a[low] : a[high]; } else { int mid = (low + high)/2; int x1, x2, y1, y2; maxmin(a, &x1, &y1, low, mid); maxmin(a, &x2, &y2, mid + 1, high); *e_max = (x1 > x2) ? x1 : x2; *e_min = (y1 < y2) ? y1 : y2; } } int main() { int a[10] = {9, 3, 6, 2, 1, 8, 4, 5, 7, 23}; int e_max, e_min, low, high; printf("输入范围: (low and high) "); scanf("%d %d", &low, &high); if (low < 0 || low >= 10 || high < 0 || high >= 10 || low >= high) { printf("超出范围\n"); return 1; // 返回非零值表示程序异常退出 } maxmin(a, &e_max, &e_min, low, high); printf("Max: %d\n", e_max); printf("Min: %d\n", e_min); return 0; } 2、分治法实现快速排序 #include <stdio.h> void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } int split(int A[], int low, int high) { int x = A[low]; // 将第一个元素作为枢轴 int i = low; for (int j = low + 1; j <= high; j++) { if (A[j] <= x) { i++; if (i != j) { swap(&A[i], &A[j]); // 交换元素 } } } swap(&A[low], &A[i]); // 交换枢轴和A[i] return i; // 返回枢轴的位置 } void quick_sort(int A[], int low, int high) { if (low < high) { int k = split(A, low, high); quick_sort(A, low, k - 1); // 对左侧子数组进行排序 quick_sort(A, k + 1, high); // 对右侧子数组进行排序 } } int main() { int arr[] = {9, 4, 6, 2, 5, 8, 4, 5, 6, 22}; int n = sizeof(arr) / sizeof(arr[0]); printf("原始数组:"); for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } printf("\n"); quick_sort(arr, 0, n - 1); printf("排序后的数组:"); for (int j = 0; j < n; j++) // 将循环中的变量重命名为 j { printf("%d ", arr[j]); } printf("\n"); return 0; } 3、贪婪法求解可分割背包问题最优解 #include <stdio.h> typedef struct { float p; float w; float v; //价值 }object; void knapsackGreedy(float M, object insurance[], int n) { int i; float m = M; float totalValue = 0.0; for (i = 0; i < n; i++) { insurance[i].v = insurance[i].p / insurance[i].w; } for (i = 0; i < n - 1; i++) // 按照单位价值降序排列物品 { for (int j = i + 1; j < n; j++) { if (insurance[j].v > insurance[i].v) { object temp = insurance[j]; insurance[j] = insurance[i]; insurance[i] = temp; } } } printf("选择的物品及其放入比例:\n"); for (i = 0; i < n; i++) { if (m >= insurance[i].w) { printf("物品%d: 1.00\n", i + 1); m -= insurance[i].w; totalValue += insurance[i].p; } else { float ratio = m / insurance[i].w; printf("物品%d: %.2f\n", i + 1, ratio); totalValue += ratio * insurance[i].p; m = 0; break; } } printf("总价值:%.2f\n", totalValue); } int main() { int n = 5; float M = 100; object in[] = {{20, 10, 0}, {30, 20, 0}, {66, 30, 0}, {40, 40, 0}, {60, 50, 0}}; knapsackGreedy(M, in, n); return 0; }
运行截图如下: