1,冒泡排序
- 基本思想:每趟排序从待排关键字记录中的第一个关键字记录与第二个关键字记录相比较,若第一个关键字大于第二个关键字,则将两者交换,再次比较第二个关键字和第三个关键字,若为逆序,则两者交换,依次类推,直至第n-1个关键字和第n个关键字比较为止。每趟排序都将一个待排关键字的位置固定,整个排序过程将进行K(1<=k<n)趟排序。
- 时间复杂度最差和平均复杂度为O(n^2),最好的时间复杂度为O(n)。
- 空间复杂度为O(1)。
- 当待排序列为正序时,比较次数为n-1,移动次数为0,需进行1趟排序。当待排序列为逆序时,比较次数为n(n-1)/2。移动次数为3*n(n-1)/2。需进行n-1趟排序。
- 稳定的排序算法。
- 对初始待排序列敏感。
代码如下:
#include "stdafx.h"
#include<stdio.h>
#define MAXSIZE 40
struct SqList{
int list[MAXSIZE+1];
int length;
};
void bubbleSort(SqList &L){
int i,j;
int temp;
bool exchange;
for(i=L.length-1;i>=0;i--)
{
exchange=false;//只要有一趟排序未发生交换,则提前终止排序,因为此时已是有序的了。
for(j=0;j<i;j++)//这里j<i,而不是j<=i。因为最后待排关键字的位置在i处,如果当j=i时,j+1>i,就不在i这个位置了。
{
if(L.list[j+1]<L.list[j])
{
temp=L.list[j+1];
L.list[j+1]=L.list[j];
L.list[j]=temp;
exchange=true;
}
}
if(!exchange)return;
}
}
void main()
{
SqList St;
printf("***********************************************\n");
printf(" 冒泡排序算法 \n");
printf("***********************************************\n");
printf("请输入需要排序的关键字个数N (N<%d):",MAXSIZE);
scanf("%d",&St.length);
printf("\n");
printf("请输入%d个待排序的关键字:\n",St.length);
for (int i=0;i<St.length;i++)
scanf("%d",&St.list[i]);
bubbleSort(St);
printf("\n");
printf("输出排序结果:");
for(int j=0;j<St.length;j++)
printf("%d ",St.list[j]);
printf("\n");
printf("\n");
}
运行结果如下:
2,快速排序
- 基本思想:通过一趟排序,将待排记录分成两个部分,其中一部分关键字记录均大于另一部分关键字记录,再对这两部分递归进行上述划分,最后当递归的两个部分关键字记录个数均为1时,则待排序列已有序。在这个操作中,利用一个枢轴值将待排记录分成两部分,该枢轴值可以是每一部分第一个关键字值。设置两个指针low和high,分别指向待排记录的第一个关键字值和最后一个关键字值,一趟划分的操作为:先从high处向左端遍历,找到第一个小于枢轴值的记录,并将该记录放在low处(因为在实际应用中,对枢轴值重复交换,浪费时间,所以是将枢轴值保存在一个变量中, 第一次交换,覆盖low处的值(也就是枢轴的值)),此时high的位置是空出的;再从low处向右遍历找到第一个大于枢轴值的记录,并将该记录放在刚刚空出来的high处,重复进行这两项操作,直到low=high为止,此时low和high的位置就是最终枢轴记录所在的记录。那么快速排序就是每次确定枢轴的位置,其操作为:当low<high时(要保证每一部分的个数大于1),找到枢轴的位置,递归左半部分,再递归右半部分。
- 时间复杂度:平均复杂度为O(nlogn),最差的情况退化为冒泡排序,时间复杂度为O(n^2)。
- 空间复杂度:O(log(n))因为有递归,所以需要占空间,当每趟排序将待排序列均匀的分成两个大小相近的子序列,所需要的栈空间最大长度为log2(n)+1(向下取整);当每趟排序,枢轴的位置都位于子序列的一端,就是最坏的情况,所需栈的最大长度为n。
- 不是稳定的排序算法。
- 对初始序列敏感。
- 快速排序,通常被认为,是所有同量级O(nlogn)排序方法中,平均性能最好的,就平均性能而言,它是目前最好的一种内部排序算法。
代码如下:
#include "stdafx.h"
#include<stdio.h>
#define MAXSIZE 40
struct SqList{
int list[MAXSIZE+1];
int length;
};
int partion(SqList&L,int low,int high)
{
L.list[0]=L.list[low];//L.list[0]为暂存单元
int pivotkey=L.list[low];//枢轴值。
while(low<high)
{
while(low<high&&L.list[high]>=pivotkey)high--;//从high往左寻找小于枢轴值的记录
L.list[low]=L.list[high];//将找到的记录值放在空出来的low处。
while(low<high&&L.list[low]<=pivotkey)low++;//从low往右寻找大于枢轴值的记录。
L.list[high]=L.list[low];//将大于枢轴值的记录放到刚刚空出来的high处。
}
L.list[low]=L.list[0];//跳出循环,一定是low=high,此时low和high处一定是空出来的。
return low;
}
void QSort(SqList&L,int low,int high)
{
int pivotloc;
if(low<high)//只要长度大于1,就要进行递归排序
{
pivotloc=partion(L,low,high);//每一次递归操作都是,找到枢轴位置.
QSort(L,low,pivotloc-1);//再在右侧序列递归.
QSort(L,pivotloc+1,high);//再在左侧序列递归.
}
}
void QuickSort(SqList &L){
QSort(L,1,L.length);
}
void main()
{
SqList St;
printf("***********************************************\n");
printf(" 快速排序算法 \n");
printf("***********************************************\n");
printf("请输入需要排序的关键字个数N (N<%d):",MAXSIZE);
scanf("%d",&St.length);
printf("\n");
printf("请输入第一个关键字值为0,为暂存单元,不参与排序,再输入%d个待排序的关键字值:\n",St.length);
for (int i=0;i<=St.length;i++)
scanf("%d",&St.list[i]);
QuickSort(St);
printf("\n");
printf("输出排序结果:");
for(int j=1;j<=St.length;j++)
printf("%d ",St.list[j]);
printf("\n");
printf("\n");
}
运行结果如下: