commit 3fb0fa3b69ac97b7dffd273c3e2c08539df8ebb6 Author: fly6516 Date: Mon Nov 18 15:42:58 2024 +0800 implement functionality diff --git a/AI/code.md b/AI/code.md new file mode 100644 index 0000000..ed391ad --- /dev/null +++ b/AI/code.md @@ -0,0 +1,130 @@ +以下是实验报告完成的详细指导和代码示例。 + +--- + +## 实验报告 + +### 一、归并排序和快速排序的基本思想 + +1. **归并排序** + - **基本思想**:归并排序基于分治思想。将数组递归地分成两个子数组,对每个子数组进行排序后再将其合并。合并时通过比较大小有序地将元素放入结果数组中。 + - **优点**:稳定排序,时间复杂度为 \(O(n \log n)\)。 + - **适用场景**:数据量大且需要稳定排序。 + +2. **快速排序** + - **基本思想**:快速排序通过选择一个基准元素(通常是数组的第一个或最后一个元素),将数组划分为比基准小和比基准大的两个子数组,然后递归地对这两个子数组进行排序。 + - **优点**:平均时间复杂度为 \(O(n \log n)\),空间复杂度低于归并排序。 + - **适用场景**:数据量大且对稳定性要求不高。 + +--- + +### 二、实验环境 +1. **操作系统**:Windows/Linux。 +2. **开发工具**:Python 3.x,Jupyter Notebook。 + +--- + +### 三、源码实现 + +#### 1. 归并排序 + +```python +def merge_sort(arr): + if len(arr) <= 1: + return arr + + # 分割数组 + mid = len(arr) // 2 + left_half = merge_sort(arr[:mid]) + right_half = merge_sort(arr[mid:]) + + # 合并数组 + return merge(left_half, right_half) + +def merge(left, right): + result = [] + i = j = 0 + + # 合并两个子数组 + while i < len(left) and j < len(right): + if left[i] <= right[j]: + result.append(left[i]) + i += 1 + else: + result.append(right[j]) + j += 1 + + # 加入剩余的元素 + result.extend(left[i:]) + result.extend(right[j:]) + return result +``` + +#### 2. 快速排序 + +```python +def quick_sort(arr): + if len(arr) <= 1: + return arr + + # 选择基准 + pivot = arr[len(arr) // 2] + left = [x for x in arr if x < pivot] + middle = [x for x in arr if x == pivot] + right = [x for x in arr if x > pivot] + + # 递归排序 + return quick_sort(left) + middle + quick_sort(right) +``` + +--- + +### 四、算法分析 + +#### 1. 归并排序 +- **时间复杂度**:分割数组和合并操作均为 \(O(n \log n)\)。 + - 最好、最坏和平均时间复杂度:\(O(n \log n)\)。 +- **空间复杂度**:需要额外存储中间数组,空间复杂度为 \(O(n)\)。 + +#### 2. 快速排序 +- **时间复杂度**: + - 最好和平均时间复杂度:\(O(n \log n)\)。 + - 最坏时间复杂度:当每次分割极不均匀时为 \(O(n^2)\)。 +- **空间复杂度**:原地排序,平均空间复杂度为 \(O(\log n)\)。 + +--- + +### 五、实验运行结果 + +#### 测试代码 + +```python +if __name__ == "__main__": + import random + + # 测试数组 + test_array = [random.randint(0, 100) for _ in range(10)] + print("原始数组:", test_array) + + # 测试归并排序 + sorted_array_merge = merge_sort(test_array) + print("归并排序结果:", sorted_array_merge) + + # 测试快速排序 + sorted_array_quick = quick_sort(test_array) + print("快速排序结果:", sorted_array_quick) +``` + +#### 运行结果截图 +运行以上代码后,实验结果显示为随机数组的排序前后对比,例如: +``` +原始数组: [35, 20, 7, 85, 50, 13, 99, 42, 15, 68] +归并排序结果: [7, 13, 15, 20, 35, 42, 50, 68, 85, 99] +快速排序结果: [7, 13, 15, 20, 35, 42, 50, 68, 85, 99] +``` + +截图保存实验运行结果以提交报告。 + +--- + +希望这份指导能够帮助您完成实验报告!需要进一步协助时,请随时提问。 \ No newline at end of file diff --git a/AI/explain.md b/AI/explain.md new file mode 100644 index 0000000..8c1388f --- /dev/null +++ b/AI/explain.md @@ -0,0 +1,152 @@ +下面对归并排序和快速排序的每一行代码进行详细的解释。 + +--- + +### **归并排序代码详解** + +#### 函数 `merge_sort` + +```python +def merge_sort(arr): + if len(arr) <= 1: + return arr +``` +- **作用**:判断数组是否只有一个元素或为空。如果是,直接返回,因为这样的数组已经是有序的。 +- **意义**:递归终止条件,避免无限递归。 + +```python + mid = len(arr) // 2 +``` +- **作用**:计算数组的中间位置,将数组分为左右两部分。 +- **意义**:分治算法的关键,将问题拆分为更小的子问题。 + +```python + left_half = merge_sort(arr[:mid]) + right_half = merge_sort(arr[mid:]) +``` +- **作用**:对左半部分和右半部分递归调用 `merge_sort`,直到每部分只有一个元素。 +- **意义**:实现递归,最终将数组拆分到最小粒度。 + +```python + return merge(left_half, right_half) +``` +- **作用**:将左右两个已排序的部分合并为一个完整的排序数组。 +- **意义**:通过合并操作完成排序过程。 + +#### 函数 `merge` + +```python +def merge(left, right): + result = [] + i = j = 0 +``` +- **作用**: + - 初始化一个空数组 `result`,用来存储合并后的有序数组。 + - 初始化两个指针 `i` 和 `j`,分别指向左数组和右数组的起始位置。 +- **意义**:合并两个有序数组的准备工作。 + +```python + while i < len(left) and j < len(right): + if left[i] <= right[j]: + result.append(left[i]) + i += 1 + else: + result.append(right[j]) + j += 1 +``` +- **作用**: + - 比较两个数组的当前元素,将较小的元素加入 `result` 中。 + - 相应的指针 (`i` 或 `j`) 向前移动。 +- **意义**:通过比较大小,确保合并后的数组有序。 + +```python + result.extend(left[i:]) + result.extend(right[j:]) +``` +- **作用**: + - 将剩余的元素(可能只在一个数组中剩余)加入 `result` 中。 +- **意义**:处理合并过程中较长数组的剩余部分。 + +--- + +### **快速排序代码详解** + +```python +def quick_sort(arr): + if len(arr) <= 1: + return arr +``` +- **作用**:判断数组是否只有一个元素或为空。如果是,直接返回。 +- **意义**:递归终止条件,避免无限递归。 + +```python + pivot = arr[len(arr) // 2] +``` +- **作用**:选择数组的中间元素作为基准。 +- **意义**:基准元素是快速排序的核心,用于将数组划分为左右两部分。 + +```python + left = [x for x in arr if x < pivot] + middle = [x for x in arr if x == pivot] + right = [x for x in arr if x > pivot] +``` +- **作用**: + - 使用列表推导式将数组分为三个部分: + - `left`:比基准小的元素。 + - `middle`:与基准相等的元素。 + - `right`:比基准大的元素。 +- **意义**:实现划分步骤,确保数组被分割为有序的三部分。 + +```python + return quick_sort(left) + middle + quick_sort(right) +``` +- **作用**: + - 对 `left` 和 `right` 两部分递归调用快速排序。 + - 将已排序的 `left`、`middle` 和 `right` 拼接为最终的结果。 +- **意义**:通过递归完成整个快速排序过程。 + +--- + +### **测试代码详解** + +```python +if __name__ == "__main__": + import random +``` +- **作用**:表示以下代码块仅在直接运行文件时执行,而在导入模块时不会执行。 +- **意义**:增强代码的复用性。 + +```python + test_array = [random.randint(0, 100) for _ in range(10)] +``` +- **作用**:生成一个包含 10 个随机整数的数组,范围在 0 到 100 之间。 +- **意义**:为测试排序算法创建样例数据。 + +```python + print("原始数组:", test_array) +``` +- **作用**:打印未排序的原始数组。 +- **意义**:用于与排序后的结果进行对比,验证算法的正确性。 + +```python + sorted_array_merge = merge_sort(test_array) + print("归并排序结果:", sorted_array_merge) +``` +- **作用**: + - 调用归并排序对数组进行排序。 + - 打印归并排序后的结果。 +- **意义**:测试归并排序的正确性。 + +```python + sorted_array_quick = quick_sort(test_array) + print("快速排序结果:", sorted_array_quick) +``` +- **作用**: + - 调用快速排序对数组进行排序。 + - 打印快速排序后的结果。 +- **意义**:测试快速排序的正确性。 + +--- + +### 总结 +通过逐行解释,我们清楚地理解了代码中每一步的作用和意义。整个实验通过递归、分治思想实现了两个经典排序算法:归并排序和快速排序。 \ No newline at end of file diff --git a/AI/report.md b/AI/report.md new file mode 100644 index 0000000..4ede8a4 --- /dev/null +++ b/AI/report.md @@ -0,0 +1,154 @@ +## 实验报告 + +### **实验1:归并排序和快速排序** + +--- + +### **一、实验目的** +1. 了解归并排序的基本原理; +2. 掌握快速排序的基本概念及实现方法; +3. 熟悉分治法的策略及其在排序算法中的应用。 + +--- + +### **二、实验环境** +1. **操作系统**:Windows 10 或 Linux; +2. **编程语言**:Python 3.x; +3. **开发工具**:Jupyter Notebook 或 PyCharm。 + +--- + +### **三、实验内容** +1. 实现归并排序算法; +2. 实现快速排序算法; +3. 对两个算法进行时间复杂度和空间复杂度分析; +4. 测试并记录实验结果。 + +--- + +### **四、实验步骤** + +#### **1. 归并排序代码实现** + +```python +def merge_sort(arr): + if len(arr) <= 1: # 递归终止条件 + return arr + + mid = len(arr) // 2 # 找到中间点 + left_half = merge_sort(arr[:mid]) # 对左半部分递归调用 + right_half = merge_sort(arr[mid:]) # 对右半部分递归调用 + + return merge(left_half, right_half) # 合并已排序的两部分 + +def merge(left, right): + result = [] + i = j = 0 + + while i < len(left) and j < len(right): # 比较并合并两部分 + if left[i] <= right[j]: + result.append(left[i]) + i += 1 + else: + result.append(right[j]) + j += 1 + + result.extend(left[i:]) # 添加剩余部分 + result.extend(right[j:]) + return result +``` + +#### **2. 快速排序代码实现** + +```python +def quick_sort(arr): + if len(arr) <= 1: # 递归终止条件 + return arr + + pivot = arr[len(arr) // 2] # 选择基准 + left = [x for x in arr if x < pivot] # 划分为小于基准的部分 + middle = [x for x in arr if x == pivot] # 等于基准的部分 + right = [x for x in arr if x > pivot] # 大于基准的部分 + + return quick_sort(left) + middle + quick_sort(right) # 递归排序并拼接结果 +``` + +#### **3. 测试代码** + +```python +if __name__ == "__main__": + import random + + test_array = [random.randint(0, 100) for _ in range(10)] # 随机生成测试数据 + print("原始数组:", test_array) + + sorted_array_merge = merge_sort(test_array) # 测试归并排序 + print("归并排序结果:", sorted_array_merge) + + sorted_array_quick = quick_sort(test_array) # 测试快速排序 + print("快速排序结果:", sorted_array_quick) +``` + +--- + +### **五、实验结果** + +#### **运行结果截图** + +运行代码后,生成的输出示例为: + +``` +原始数组: [35, 20, 7, 85, 50, 13, 99, 42, 15, 68] +归并排序结果: [7, 13, 15, 20, 35, 42, 50, 68, 85, 99] +快速排序结果: [7, 13, 15, 20, 35, 42, 50, 68, 85, 99] +``` + +截图展示运行前后的数组对比,验证算法的正确性。 + +--- + +### **六、算法分析** + +#### **1. 归并排序分析** + +- **时间复杂度**: + - 分割数组的时间复杂度为 \(O(\log n)\)。 + - 合并操作的时间复杂度为 \(O(n)\)。 + - 总时间复杂度为 \(O(n \log n)\)。 +- **空间复杂度**: + - 需要额外的临时数组来存储中间结果,空间复杂度为 \(O(n)\)。 +- **稳定性**: + - 归并排序是稳定的,因为在合并时保持了元素的相对顺序。 + +#### **2. 快速排序分析** + +- **时间复杂度**: + - 平均情况:每次划分数组为两部分,时间复杂度为 \(O(n \log n)\)。 + - 最坏情况:当划分极不均匀时,时间复杂度为 \(O(n^2)\)。 +- **空间复杂度**: + - 原地排序,不需要额外的存储空间,空间复杂度为 \(O(\log n)\)(递归栈空间)。 +- **稳定性**: + - 快速排序是不稳定的,因为在分区时元素的相对顺序可能会改变。 + +--- + +### **七、实验总结** + +1. **实验收获**: + - 理解了分治法的基本思想,并能将其应用于排序算法中。 + - 掌握了归并排序和快速排序的代码实现及其优化方法。 + - 理解了两种算法在不同场景下的性能优劣。 + +2. **两种算法对比**: + - 归并排序适合需要稳定排序且对内存消耗不敏感的场景。 + - 快速排序适合对时间要求较高且数据量较大的场景,但对最坏情况的优化尤为重要。 + +3. **进一步优化建议**: + - 快速排序可以通过随机化基准元素选择或三路划分优化最坏情况性能。 + - 对归并排序可使用原地合并技术降低空间复杂度。 + +--- + +### **附录:完整代码** + +将归并排序和快速排序代码整合为一个文件,附加到实验报告中以便查阅和调试。 \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..bb212c8 --- /dev/null +++ b/main.py @@ -0,0 +1,17 @@ +import merge_sort +import quick_sort + +if __name__ == "__main__": + import random + + # 测试数组 + test_array = [random.randint(0, 100) for _ in range(10)] + print("原始数组:", test_array) + + # 测试归并排序 + sorted_array_merge = merge_sort.merge_sort(test_array) + print("归并排序结果:", sorted_array_merge) + + # 测试快速排序 + sorted_array_quick = quick_sort.quick_sort(test_array) + print("快速排序结果:", sorted_array_quick) diff --git a/merge_sort.py b/merge_sort.py new file mode 100644 index 0000000..485ea26 --- /dev/null +++ b/merge_sort.py @@ -0,0 +1,30 @@ +def merge_sort(arr): + if len(arr) <= 1: + return arr + + # 分割数组 + mid = len(arr) // 2 + left_half = merge_sort(arr[:mid]) + right_half = merge_sort(arr[mid:]) + + # 合并数组 + return merge(left_half, right_half) + + +def merge(left, right): + result = [] + i = j = 0 + + # 合并两个子数组 + while i < len(left) and j < len(right): + if left[i] <= right[j]: + result.append(left[i]) + i += 1 + else: + result.append(right[j]) + j += 1 + + # 加入剩余的元素 + result.extend(left[i:]) + result.extend(right[j:]) + return result diff --git a/quick_sort.py b/quick_sort.py new file mode 100644 index 0000000..753813e --- /dev/null +++ b/quick_sort.py @@ -0,0 +1,12 @@ +def quick_sort(arr): + if len(arr) <= 1: + return arr + + # 选择基准 + pivot = arr[len(arr) // 2] + left = [x for x in arr if x < pivot] + middle = [x for x in arr if x == pivot] + right = [x for x in arr if x > pivot] + + # 递归排序 + return quick_sort(left) + middle + quick_sort(right)