一、选择排序
1.基本思想
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据全部排完。
2.直接选择排序
(1) 在元素集合arr[i] — arr[n - 1]中选择关键妈的最大(小)的数据元素
(2) 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素的最后一个(第一个)元素交换
(3) 在剩余的arr[i] — arr[n - 2](arr[i + 1] — arr[n - 1])集合中,重复上述步骤,知道集合剩余1个元素
3.直接选择排序的特性总结
(1)直接选择排序的效率不高,实际中很少用
(2)时间复杂度:
(3)空间复杂度:
(4)稳定性:不稳定
4.图示
//选择排序
void SelectSort2(int* arr, int n)
{for (int j = 0; j < n; j++){for (int i = j + 1; i < n; i++){if (arr[i] < arr[j]){swap(&arr[j], &arr[i]);}}}
}
5.选择排序优化
用begin和end来做边界,maxi和mini来记录数组中最大值和最小值的下标。
//选择排序优化
void SelectSort(int* arr, int n)
{int begin = 0,end = n - 1;while (begin < end){int mini = begin, maxi = begin;for (int i = begin + 1; i <= end; i++){if (arr[i] < arr[mini]){mini = i;}if (arr[i] > arr[maxi]){maxi = i;}}swap(&arr[mini], &arr[begin]);if (begin == maxi){maxi = mini;}swap(&arr[maxi], &arr[end]);--end;++begin;}
}
二、冒泡排序
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有在需要交换,也就是说该数列已经排序完成。这个算法的名字由来是应为越小的元素会经由交换慢慢“浮”到数列的顶端。
1.算法描述
(1) 比较相邻的元素。如果第一个比第二个大,就交换它们两个
(2) 对每一对相邻元素作相同的工作,从第一对到结尾最后一对,这样在最后的元素就是最大的数
(3)针对所有的元素重复以上的步骤
(4)重复步骤1—3,直到排序完成
2.动图演示
3.代码演示
//冒泡排序
// O(N^2)最坏
// O(N)最好
void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void BubbleSort(int* arr, int n)
{for (int j = 0; j < n; j++){int flag = 0;//用来记录是否发生交换for (int i = 0; i < n - 1; i++){if (arr[i] > arr[i + 1]){swap(&arr[i], &arr[i + 1]);flag = 1;}}if (flag == 0){//一趟下来没有交换,说明已经有序,跳出循环 break;}}
}
三、选择排序与冒泡排序效率对比
void TestOP()
{srand(time(0));const int N = 50000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){a1[i] = a1[i];a2[i] = a1[i];}int begin1 = clock();SelectSort(a3, N);int end1 = clock();int begin2 = clock();BubbleSort(a6, N);int end2 = clock();printf("SelectSort:%d\n", end1 - begin1);printf("BubbleSort:%d\n", end2 - begin2);free(a1);free(a2);}int main()
{int arr[] = { 9,1,2,5,7,4,6,3,8 };int sz = sizeof(arr) / sizeof(arr[0]);TestOP();return 0;
}
对50000个随机数进行排序,两种排序所用时间如下图: