一、排序的概念
排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序,若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。本文所介绍的是内部排序。
二、插入排序
1、概念
- 思路:每一次在 n-i+1 (i=1, 2, 3, …, n-1)个记录中选取关键字最小的记录作为有序序列的第 i 个记录。
- 分类:直接选择排序、堆排序
2、直接选择排序
直接选择排序:直接选择排序是非稳定的排序方法。在直接选择排序中,共需要进行n-1次选择和交换,每次选择需要进行 n-i 次比较 (1<=i<=n-1), 而每次交换最多需要3次移动,因此,总的比较次数 C=(n*n - n)/2 ,总的移动次数 3(n-1) .由此可知,直接选择排序的时间复杂度为 O(n^2) ,所以当记录占用字节数较多时,通常比直接插入排序的执行速度快些。
思路:第 1 次从 array[0]~array[n-1] 中选取最小值,与 array[0] 交换,…,第 i 次从 array[i-1]~array[n-1] 中选取最小值,与 array[i-1] 交换…,第n-1次从 array[n-2]~array[n-1] 中选取最小值,与 array[n-2] 交换,总共通过n-1次,得到一个从小到大排列的有序序列。所以需要两层循环,第一层循环实现第i次交换,第二层循环实现寻找最小值。
代码如下:
#include <iostream>
using namespace std;
// 选择排序, 每次找到最小的内容放到最开始。
void selectSort(int numArray[], int sum){
int index = 0;
// 寻找index~n-1的最小值放到array[index]中。
for(; index < sum-1; index++){
int minNum = numArray[index]; //记录最小值的大小
int minPos = index; // 记录最小值的位置
// 寻找最小值, 每次遇到更小的元素更新最小值和位置。
for(int minIndex = index; minIndex < sum; minIndex++){
if(minNum > numArray[minIndex]){
minPos = minIndex;
minNum = numArray[minIndex];
}
}
swap(numArray[index], numArray[minPos]);
}
}
int main(){
int sum = 10;
int arr[100] = {45,10,25,1,9,56,99,100,3,120};
cout << "排序前:";
for(int i = 0; i < sum; i++)
cout << arr[i]<< " ";
cout << "\n";
selectSort(arr, sum);
cout << "排序后:";
for(int i = 0; i < sum; i++)
cout << arr[i]<< " ";
cout << "\n";
return 0;
}
2、堆排序
堆排序:堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),同时也是非稳定排序。
思路:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将根节点与末尾元素进行交换,此时最大值来到的末尾。然后将剩余n-1个元素重新构造成一个大顶堆,在进行根节点与末尾元素的交换。重复上述步骤,就能够得到一个从小到大的有序序列。
推荐大家看一下这片文章,关于堆排序讲的非常明白详细,不过给出的代码是Java的:https://blog.csdn.net/u010452388/article/details/81283998
C++代码如下:
#include <iostream>
using namespace std;
// 对堆进行调整使其变成大顶堆
void adjustHeap(int numArray[], int pos, int sum){
// 记录当前堆的根节点,如果根节点关键字比较小会和下面的节点进行交换。
int tempNum = numArray[pos];
for(int index = pos*2+1; index < sum; index=index*2+1){
// 如果右面的子节点更大,就将位置记录为右节点。
if(index+1 < sum && numArray[index] < numArray[index+1]){
index++;
}
/*
如果最开始的根节点值比较当前节点小,把当前子节点赋值到其父节点上
发生了该步骤,说明根节点比较小,需要更新根节点最终插入的位置。
*/
if(tempNum < numArray[index]){
numArray[pos] = numArray[index];
pos = index;
}
/*
因为最开始根节点的子节点都是大顶堆,
所以如果根节点比当前节点更大,就不需要往下走了
*/
else{
break;
}
}
numArray[pos] = tempNum;
}
// 堆排序
void heapSort(int numArray[], int sum){
for(int start = (sum+1)/2-1; start >= 0; start--){
adjustHeap(numArray, start, sum);// 对堆进行调整。
}
for(int length = sum-1; length>0 ; length--){
swap(numArray[0], numArray[length]);// 将堆顶元素与末尾元素进行交换。
adjustHeap(numArray, 0, length);// 重新对堆进行调整。
}
}
int main(){
int sum = 10;
int arr[100] = {45,10,25,1,9,56,99,100,3,120};
cout << "排序前:";
for(int i = 0; i < sum; i++)
cout << arr[i]<< " ";
cout << "\n";
heapSort(arr, sum);
cout << "排序后:";
for(int i = 0; i < sum; i++)
cout << arr[i]<< " ";
cout << "\n";
return 0;
}