排序基础(一)
来源:互联网 发布:点评10月的经济数据 编辑:程序博客网 时间:2024/06/15 14:47
排序算法
O(n2)的排序算法
为什么要学习O(n2)的排序算法?
- 基础
- 编码简单,易于实现,是一些简单场景的首选
- 在一些特殊情况下,简单的排序算法更有效
- 简单的排序算法思想衍生出复杂的排序算法
- 作为子过程,改进更复杂的排序算法
选择排序(Selection Sort)
算法思想:每一趟(例如第i趟)在后面n-i+1(i=1,2,3,···,n-1)个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到第n-1趟做完,待排序元素只剩下1个,就不用再选了。
算法动画演示:
基本算法如下:
#include <iostream>using namespace std;void selectionSort(T arr[], int n) { for (int i = 0; i < n - 1; i++) { // 寻找[i, n)区间里的最小值 int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } if (minIndex != i) swap(arr[i], arr[minIndex]); }}int main(void) { int a[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; selectionSort(a, 10); for (int i = 0; i < 10; i++) cout << a[i] << " "; cout << endl; return 0;}
其运行结果为:
1 2 3 4 5 6 7 8 9 10
但上述算法存在一些问题,如果我们想要对浮点数、字符串等进行排序,上述代码就不能满足我们的需求,那我们要如何做才能解决这个问题呢?熟悉C++语言或者Java语言的同学就会知道,可以使用C++中的模板或者使用Java中的泛型来解决此问题。此处,我们以C++语言为例,代码如下:
#include <iostream>using namespace std;template<typename T>void selectionSort(T arr[], int n) { for (int i = 0; i < n - 1; i++) { // 寻找[i, n)区间里的最小值 int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } if (minIndex != i) swap(arr[i], arr[minIndex]); }}int main(void) { int a[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; float b[10] = {10, 9.6, 8, 7.9, 6.3, 5, 4.1, 3, 2, 1.6}; string c[4] = {"D", "A", "C", "B"}; selectionSort(a, 10); for (int i = 0; i < 10; i++) cout << a[i] << " "; cout << endl; selectionSort(b, 10); for (int i = 0; i < 10; i++) cout << b[i] << " "; cout << endl; selectionSort(c, 4); for (int i = 0; i < 4; i++) cout << c[i] << " "; cout << endl; return 0;}
其运行结果为:
1 2 3 4 5 6 7 8 9 101.6 2 3 4.1 5 6.3 7.9 8 9.6 10A B C D
如果我们要按结构体变量中的某个成员从小到大排序,那代码如何实现?这里,我们先创建Student.h这个头文件,代码如下:
#ifndef SELECTIONSORT_STUDENT_H#define SELECTIONSORT_STUDENT_H#include <iostream>using namespace std;struct Student { string name; int score; // 重载< bool operator<(const Student &otherStudent) { return score != otherStudent.score ? score < otherStudent.score : name < otherStudent.name; } // 重载<< friend ostream &operator<<(ostream &os, const Student &student) { os << "Student: " << student.name << " " << student.score << endl; return os; }};#endif //SELECTIONSORT_STUDENT_H
然后我们将之前的代码修改如下即可:
#include <iostream>#include "Student.h"using namespace std;template<typename T>void selectionSort(T arr[], int n) { for (int i = 0; i < n - 1; i++) { // 寻找[i, n)区间里的最小值 int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } if (minIndex != i) swap(arr[i], arr[minIndex]); }}int main(void) { Student d[4] = { {"D", 90}, {"A", 100}, {"C", 78}, {"B", 89} }; selectionSort(d, 4); for (int i = 0; i < 4; i++) cout << d[i]; cout << endl; return 0;}
其运行结果为:
Student: C 78Student: B 89Student: D 90Student: A 100
虽然,我们完善了我们的程序,使我们的程序可以对int、float和string等类型排序,但纵观我们的程序,始终有个小问题,就是我们的测试用例不是很智能。因此,我们创建SortTestHelper.h文件,其代码如下:
#ifndef SELECTIONSORT_SORTTESTHELPER_H#define SELECTIONSORT_SORTTESTHELPER_H#include <iostream>#include <ctime>#include <cassert>using namespace std;namespace SortTestHelper { // 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR] int *generateRandomArray(int n, int rangeL, int rangeR) { assert(rangeL <= rangeR); int *arr = new int[n]; srand(time(NULL)); for (int i = 0; i < n; i++) // 控制随机数的取值范围 arr[i] = rand() % (rangeR - rangeL + 1) + rangeL; return arr; }}#endif //SELECTIONSORT_SORTTESTHELPER_H
好了,我们回到main函数中,调用我们刚刚创建的generateRandomArray(),代码如下:
#include <iostream>#include "Student.h"#include "SortTesthelper.h"using namespace std;template<typename T>void selectionSort(T arr[], int n) { for (int i = 0; i < n - 1; i++) { // 寻找[i, n)区间里的最小值 int minIndex = i; for (int j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } if (minIndex != i) swap(arr[i], arr[minIndex]); }}int main(void) { int n = 10000; int *arr = SortTestHelper::generateRandomArray(n, 0, n); selectionSort(arr, n); for (int i = 0; i < n; i++) cout << arr[i] << " "; cout << endl; delete[] arr; return 0;}
我们又进一步完善了我们的程序,让我们在想想看还有没有地方我们可以继续优化呢?不知道大家有没有注意到结果打印代码,这几行代码我们已经重复了好几遍了!因此,我们可以对结果打印代码进行优化,我们在SortTestHelper.h文件中添加如下代码:
template<typename T> void printArray(T arr[], int n) { for (int i = 0; i < n; i++) cout << arr[i] << " "; cout << endl; }
我们在main函数中只要添加如下代码就可调用printArray()了:
SortTestHelper::printArray(arr, n);
为了使我们的程序更加完善,我们继续在SortTestHelper.h文件中添加验证排序算法执行是否正确的函数isSorted(),其代码如下:
// 验证排序算法是否执行正确 template<typename T> bool isSorted(T arr[], int n) { for (int i = 0; i < n - 1; i++) if (arr[i] > arr[i + 1]) return false; return true; }
除此之外,我们在SortTestHelper.h文件中添加testSort()来测试我们排序算法的性能,其代码如下:
// 测试排序算法的性能 template<typename T> void testSort(string sortName, void(*sort)(T[], int), T arr[], int n) { clock_t startTime = clock(); sort(arr, n); clock_t endTime = clock(); assert(isSorted(arr, n)); cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl; return; }
好了,我们在main()调用我们刚刚添加的方法吧,代码如下:
SortTestHelper::testSort("Selection Sort", selectionSort, arr, n);
- 排序基础(一)
- 排序一--基础排序
- 排序一--基础排序
- 排序算法(一)基础概览
- Swift编程基础之排序(一)
- c语言基础算法(一)---排序
- 排序算法大杂烩(一)——基础排序
- 基础算法(一):选择排序和冒泡排序
- PHP基础排序算法(一)冒泡排序
- 几个基础排序算法(一)
- 排序算法(一) - 基础篇
- 算法与数据结构基础(一)排序基础1.选择排序
- 基础笔记:排序算法(一)(选择、插入、冒泡)
- 基础算法与实现(一)——排序算法
- 基础算法系列(一)——选择排序
- 数据结构基础 排序算法(一) 概念篇
- (Basic algorithm学习笔记)《基础算法一》- 排序
- 算法导论(一)2、算法基础-插入排序 java
- c# UILearning
- 分页前台展示备忘
- 关于售前、售后、产品、市场、销售几个部门职能的理解
- 同余方程-NOIP2012TGD2T1
- 菜鸟填坑
- 排序基础(一)
- bootstrap之组件
- 排序基础(二)
- HTML入门笔记17-HTML中图片内嵌链接
- 初识Struts2
- MyBatis入门配置及简单应用
- 机器学习(一)
- 代码之髓读后感——容器&并发
- hdu6055Regular polygon