选择排序:
#include "stdafx.h"
void Output(int a[],int n)
{
for(int i=0; i<n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
// () 5,3,4,2,7,6,1,8
//第0趟: (1),3,4,2,7,6,5,8
//第1趟: (1,2),4,3,7,6,5,8
//第2趟: (1,2,3),4,7,6,5,8
// ....
//第n-2趟:(1,2,3,4,5,6,7),8
void SelectSort(int a[],int n)
{
for(int i=0; i<n-1; i++)
{
// 在a[i]...a[n-1]中,找最小值的下标
int imin=i;
for(int j=i+1; j<n; j++)
if(a[j]<a[imin])
imin=j;
if(imin!=i)
{
int tmp=a[i]; a[i]=a[imin]; a[imin]=tmp;
}
Output(a,n);
}
}
int main()
{
int a[]={5,3,4,2,7,6,1,8},n=8;
Output(a,n);
SelectSort(a,n);
Output(a,n);
return 0;
}
原理:
首先,在未排序序列中找到最小(大)的元素,存放到排序序列的起始位置。
然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
直到排序完成。
局限性:
时间复杂度为 O(n^2),对于较大规模的数据排序效率低。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
插入排序:
#include "stdafx.h"
void Output(int a[],int n)
{
for(int i=0; i<n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
// (5),3,4,2,7,6,1,8
//第1趟:(3,5),4,2,7,6,1,8
//第2趟:(3,4,5),2,7,6,1,8 tmp:4
//第3趟:(2,3,4,5),7,6,1,8 tmp:2
// ....
//第n-1趟:
void InsertSort(int a[],int n)
{
int i,j;
for(i=1; i<n; i++)
{
// 将a[i]插入到有序子序列a[0]...a[i-1]中
int tmp =a[i]; // 让位
for(j=i-1; j>=0 && a[j]>tmp; j--) // 大数
a[j+1]=a[j]; // 后移
a[j+1] = tmp; // 到位
Output(a,n);
}
}
int main(int argc, char* argv[])
{
int a[]={5,3,4,2,7,6,1,8},n=8;
Output(a,n);
InsertSort(a,n);
Output(a,n);
return 0;
}
原理:
首先,将数组视为两部分,一部分是已排序的部分,另一部分是未排序的部分。
然后,每次从未排序的部分取出一个元素,在已排序的部分找到合适的位置将其插入,使得已排序部分仍然保持有序。
局限性:
时间复杂度为O(n^2),因此对于较大规模的数据排序效率同样低。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
冒泡排序:
#include "stdafx.h"
void Output(int a[],int n)
{
for(int i=0; i<n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
//冒泡 5,3,4,2,7,6,1,8
//第0趟: (1),5,3,4,2,7,6,8
//第1趟: (1,2),5,3,4,6,7,8
//第2趟: (1,2,3),5,4,6,7,8
// ....
//第n-2趟:
void BubbleSort1(int a[],int n)
{
int i,j, tmp;
for(i=0; i<n-1; i++)
{
for(j=n-1; j>i; j--)
if(a[j-1] > a[j])
{
tmp=a[j-1]; a[j-1]=a[j]; a[j]=tmp;
}
Output(a,n);
}
}
//沉底 5,3,4,2,7,6,1,8
//第0趟: 3,4,2,5,6,1,7,(8)
//第1趟: 3,2,4,5,1,6,(7,8)
//第2趟: 2,3,4,1,5,(6,7,8)
// ....
//第n-2趟:
void BubbleSort2(int a[],int n)
{
int i,j, tmp;
for(i=0; i<n-1; i++)
{
for(j=0; j<n-i-1; j++)
if(a[j] > a[j+1])
{
tmp=a[j]; a[j]=a[j+1]; a[j+1]=tmp;
}
Output(a,n);
}
}
int main(int argc, char* argv[])
{
int a[]={5,3,4,2,7,6,1,8},n=8;
Output(a,n);
BubbleSort2(a,n);
Output(a,n);
return 0;
}
原理:
先依次比较相邻的元素,将较大(或较小)的元素交换至右侧。
每一轮遍历都会将未排序部分中最大(或最小)的元素“浮”到最右侧。
局限性:
时间复杂度为 O(n^2)同上。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
由上
推荐一个高效的排序方法:堆排序
#include <iostream>
using namespace std;
// 交换函数
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
// 对以某个节点为根的子树进行堆调整,使其满足堆的性质。
void heapify(int arr[], int n, int i) {
int largest = i; // 初始化父节点为最大值。
int left = 2 * i + 1; // 左子节点。
int right = 2 * i + 2; // 右子节点。
// 如果左子节点比父节点大,则更新最大值索引。
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
// 如果右子节点比父节点大,则更新最大值索引。
if (largest != i) {
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
// 如果最大值不是父节点,则交换并递归调整。
}
// 堆排序函数。
void heapSort(int arr[], int n) {
// 构建堆(初始化堆),
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// 一个个从堆顶取出元素,
for (int i = n - 1; i > 0; i--) {
swap(arr[0], arr[i]); // 将当前最大值移动到末尾,
heapify(arr, i, 0); // 调整剩余元素成为堆,
}
}
int main() {
int arr[] = {12, 11, 13, 5, 6, 7};
int n = sizeof(arr) / sizeof(arr[0]);//简便地搞出元素个数,
cout << "原数组:" << endl;
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
heapSort(arr, n);
cout << "堆排序后的数组:" << endl;
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
原理:
基于完全二叉树结构,它利用堆这种数据结构进行排序。将待排序的序列构建成一个大顶堆(或小顶堆)。对于大顶堆,父节点的值大于等于子节点的值;对于小顶堆,父节点的值小于等于子节点的值。。。
优点:
时间复杂度为O(n log n),相比于上述方法快。
不需要额外空间,属于原地排序算法。
局限性:
难。