1.选择排序
思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
void selectionsort(int a[],int n)
{
for(int i=0;i<=n-1;i++)
{
int min=a[i];
int min_index=i;
for(int j=i;j<=n-1;j++)
{
if(a[j]<min)
{
min=a[j];
min_index=j;
}
}
if(min_index!=i)
{
swap(a[i],a[min_index]);
}
}
}
2.快速排序
思想:通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
void quicksort(int a[],int low,int high)
{
if(low>=high)
return;
int i=low;
int j=high;
int key=a[i];
while(i<j)//key自动覆盖数组的第一个数据
{
//从右向左搜索,直到搜索到的数大于等于开始记录的数,交换其位置
while(i<j&&a[j]>=key)
j--;
if(i<j)
a[i]=a[j];
//从左向右搜索,直到搜索到的数小于等于开始记录的数,交换其位置
while(i<j&&a[i]<=key)
i++;
if(i<j)
a[j]=a[i];
}
a[i]=key;
quicksort(a,low,i-1);
quicksort(a,i+1,high);
}
3.冒泡排序
思想:用二重循环实现,外循环变量设为i,内循环变量设为j,对所有相邻记录的关键字值进行比效,如果a[j]>a[j+1],则将其交换,最终达到有序化
void Bubblesort(int a[],int n)
{
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(a[j]>a[j+1]
{
swap(a[j],a[j+1]);
}
}
}
}
4.插入排序
思想:将整个数组a分为有序和无序的两个部分。前者在左边,后者在右边。开始有序的部分只有a[0] , 其余都属于无序的部分。每次取出无序部分的第一个(最左边)元素,把它加入有序部分。假设插入合适的位置p,则原p位置及其后面的有序部分元素都向右移动一个位置,有序的部分即增加了一个元素。一直做下去,直到无序的部分没有元素。
void insertionsort(int a[],int n)
{
for(int i=1;i<size;i++)
{
//a[i]是最左边的无序元素,每次循环将a[i]放到合适位置
for(int j=0;j<i;j++)
{
if(a[j]>a[i])
{
//要把a[i]放到位置j,原下标j到i-1的元素都往后移一位
int temp=a[i];
for(int k=i;k>j;k--)
a[k]=a[k-1];
a[j]=temp;
break;
}
}
}
5.希尔排序
思想:希尔排序(Shell Sort)又称为“缩小增量排序”。先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
void shsort(int a[],int n)
{
int i,j,d;
d=n/2;/*确定固定增虽值*/
while(d>=1)
{
for(i=d+1;i<=n;i++)/*数组下标从d+1开始进行直接插入排序*/
{
a[0]=a[i];/*设置监视哨*/
j=i-d; /*确定要进行比较的元素的最右边位置*/
while((j>0)&&(a[0]<a[j]))
{
a[j+d]=a[j];/*数据右移*/
j=j-d; /*向左移d个位置V*/
}
a[j+d]=a[0]; /*在确定的位罝插入s[i]*/
}
d=d/2; /*增里变为原来的一半*/
}
return 0;
}
}
6.归并排序
思想:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
#include<iostream>
using namespace std;
void merge(int a[], int start, int mid, int end)
{
int *tmp = (int *)malloc((end-start+1)*sizeof(int));
int i = start;
int j = mid + 1;
int k = 0;
while(i <= mid && j <= end)
{
if (a[i] <= a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while(i <= mid)
tmp[k++] = a[i++];
while(j <= end)
tmp[k++] = a[j++];
for (i = 0; i < k; i++)
a[start + i] = tmp[i];
free(tmp);
};
void mergeSort(int a[], int start, int end)
{
if(a==NULL || start >= end)
return ;
int mid = (end + start)/2;
mergeSort(a, start, mid);
mergeSort(a, mid+1, end);
merge(a, start, mid, end);
};
7.堆排序
思想:堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
void Heap_build(int a[],int root,int length)
{
int lchild = root*2+1;//根节点的左子结点下标
if (lchild < length)//左子结点下标不能超出数组的长度
{
int flag = lchild;//flag保存左右节点中最大值的下标
int rchild = lchild+1;//根节点的右子结点下标
if (rchild < length)//右子结点下标不能超出数组的长度(如果有的话)
{
if (a[rchild] > a[flag])//找出左右子结点中的最大值
{
flag = rchild;
}
}
if (a[root] < a[flag])
{
//交换父结点和比父结点大的最大子节点
swap(a[root],a[flag]);
//从此次最大子节点的那个位置开始递归建堆
Heap_build(a,flag,length);
}
}
}
void Heap_sort(int a[],int len)
{
for (int i = len/2; i >= 0; --i)//从最后一个非叶子节点的父结点开始建堆
{
Heap_build(a,i,len);
}
for (int j = len-1; j > 0; --j)//j表示数组此时的长度,因为len长度已经建过了,从len-1开始
{
swap(a[0],a[j]);//交换首尾元素,将最大值交换到数组的最后位置保存
Heap_build(a,0,j);//去除最后位置的元素重新建堆,此处j表示数组的长度,最后一个位置下标变为len-2
}
}
几种算法的时间复杂度比较