选择排序—简单选择排序(Simple Selection Sort)
(我的最爱,最先想到的排序算法)
基本思想:
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
我的code:
a[]:待排序的数组
n: 数组的大小
n = sizeof(a)/sizeof(a[0]);
void SimSelectSort(int a[],int n)
{
int tmp=0;
// i 0~8 9次排序完成
// i值控制着 排序的趟 数
for(int i=0;i<n-1;i++)
{
//j 1~9
//j 控制要比较数值的序号
for(int j=i+1;j< n ;j++)
{
//每一次排序后,最小的上浮。
if(a[i]>a[j])
{
tmp =a[j];
a[j] = a[i];
a[i] = tmp;
}
}
cout << a[i] << " ";
}
}
该算法的时间复杂度为:O(n^2)
交换排序—冒泡排序(Bubble Sort)
(容易跟选择排序搞混)
基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
我的code:
void BubbleSort(int a[],int n)
{
int tmp=0;
// 1-9
for(int i=1;i<n;i++)
{
//j 0----(n-i-1)
//初始值:0 --- 8控制趟数
for(int j=0;j< n-i ;j++)
{
//每一次排序后,小的上浮,大的下沉。
//每一趟走完,最大值沉底
if(a[j]>a[j+1])
{
tmp =a[j+1];
a[j+1] = a[j];
a[j] = tmp;
}
//下面两个if只是为了突出显示每一趟的最大值
//输出最后的大值
if( j == n-i-1)
{
cout << a[j+1] << " " ;
}
//输出最小值,第一个元素
if(j==0 && (n-i-1) == 0)
{
cout << a[j] << " " ;
}
}
}
}
该算法的时间复杂度为:O(n^2)
对冒泡算法的改进
1.设置一标志性变量exchange,用于标志某一趟排序过程中是否有数据交换,如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好,可立即结束排序,避免不必要的比较过程。
插入排序—直接插入排序(Straight Insertion Sort)
基本思想:
将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用
算法的稳定性:
如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
我的code:
void SimInsertSort(int a[],int n)
{
for(int i=1;i<n;i++)
{
if(a[i] < a[i-1]) //第i个元素小于前一个元素,直接插入
{
int j = i-1;
int x =a[i]; //复制为哨兵
a[i] = a[i-1] ; //先后移动一个元素
while( x < a[j] )
{
a[j+1] = a[j];
j--; //元素后移
}
a[j+1] = x; //插入到正确的位置
}
}
}
该算法的时间复杂度为:O(n^2),由此分出的排序算法有二分插入排序,2-路插入排序。
快速排序–(Quick Sort)
基本思想:
(一般取第一个元素)
1)选择一个基准元素,通常选择第一个元素或者最后一个元素,
2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
3)此时基准元素在其排好序后的正确位置
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
我的Code:
//交换函数
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//打印输出函数
void print(int a[], int n)
{
for(int j=0;j<n;j++)
{
cout << a[j] << " " ;
}
cout << endl;
}
//以基准元素为标杆的分组函数
int partition(int a[],int low,int high)
{
int pivotKey = a[low];//基准元素
while(low < high)
{
//从high所指向的位置向前搜索,至多到low+1
//比基准小的元素交换到低端
while(low < high && a[high] >= pivotKey )
{
//比基准大 ,不交换,继续往前
--high;
}
//后半部分比基准小的,要交换
swap(&a[low],&a[high]);
print(a,10);
while(low < high && a[low] <= pivotKey)
{
++low;
}
swap(&a[low],&a[high]);
print(a,10);
}
print(a,10);
cout << "一趟分表完成" <<endl;
return low;
}
//递归调用partition函数,实现快速排序
void quickSort(int a[],int low,int high)
{
if(low < high)
{
int pivotLoc = partition(a,low,high); //通过pivotLoc值,将表一分为二
quickSort( a, low, pivotLoc - 1); //递归对低子表递归排序
quickSort( a, pivotLoc + 1, high); //递归对高子表递归排序
}
}
给定输入:int int_arr[] = { 7,6,3,1,2,9,11,10,8,5 };
程序输出结果:
算法性能分析:
**时间复杂度:O(nlog2^n)
空间复杂度:O(nlog2^n)
算法是不稳定的;**