排序的分类
主要分为两大类:内部排序:待排序的记录全部存放在计算机内存中进行的排序过程
外部排序:待排序的记录数量很大,内存不能存储全部记录,需要对外存进行访问的的排序过程
我们主要研究内部排序的方法,包括:插入排序,交换排序,选择排序和归并排序等.
几种主要的排序(以从小到大为例)
1直接插入排序(属于插入排序)
基本思想:依次将每个记录插入到一个已排好序的有序表中,从而得到一个新的、记录数增加1的有序表。
代码:void StraightInsertSort(List R,int n) { int i ,j ;
{ for(i=2;i<=n;i++) //n为表长,从第二个记录起进行插入
{ R[0]=R[i]; //第i个记录复制为岗哨
j=i-1;
while (R[0].key<R[j].key) //与岗哨相比较,直至键值不大于岗哨键值
{ R[j+1]=R[j];
j--;
}
R[j+1]=R[0]; //将第i个记录插入到序列中
}
}
图解:
若n个值排序,则需要插入n-1次,第一次是将第二个值插入只有一个值的序列中。第二次是将第三个值按递增的次序插入到已经排好序的前两个值中。后面都是如此进行。排序过程就如这个下三角型一样。
2.冒泡排序(属于交换排序)
基本思想:将第一个记录的键值和第二个记录的键值进行比较,如果逆序,则将这两个记录交换,然后继续比较第二个 和第三个记录的键值。依次类推,直到完成第n-1个记录和第n个记录的键值比较交换为止。上述过程称为第一趟起泡,其结果是键值最大的记录移到第n个位置上。然后再进行第二趟起泡排序,后面都是如此。
代码:void BubbleSort(List R,int n)
{ int i,j,temp,endsort;
for(i-1;i<=n-1;i++)
{ endsort=0;
for(j=1;j<=n-i-1;j++)
{ if (R[j].key>R[j+1].key)
{ temp=R[j];
R[j]=R[j+1];
R[j+1]=temp;
endsort=1;
}
}
if (endsort==0) break;
}
}
图解:
每一次起泡,都先将最大值沉到水底。直到将所有值排好序。
3.快速排序(属于交换排序,是冒泡排序的一种改进)
基本思想:在n个记录中取某一个记录的键值作为标准,通常取第一个记录键值为基准,通过一趟排序将待排的记录分为小于或等于这个键值和大于这个键值的两个独立的部分,这时一部分的记录键值均比另一部分记录的键值小,然后对这两部分记录继续分别进行快速排序,以达到整个序列有序。
代码:int QuickPartition(List R,int low,int high)
{ x=R[low];
while(low<high)
{
while((low<high)&&(R[high].key>=x.key)) high--;
R[low]=R[high];
while((low<high)&&(R[low].key<=x.key)) low++;
R[high]=R[low];
}
R[low]=x;
return low;
}
void QuickSort(List R,int low,int high)
{ if (low<high)
{
temp=QuickPartition(R,low,high);
QuickSort(R,low,temp-1);
QuickSort(R,temp+1,high);
}
图解:
每一次调用QuickSort函数得到的效果都是以某一个值为标准,它的左边都是比它大的,而右边都是比它小的。采用递归的方法,依次以逐渐变小的范围进行这样排序,直到完成排序为止。
4.直接选择排序(属于选择排序)
基本思想:每一次n-i+1(i=1,2,…,n=1)个记录中选取键值最小的记录作为有序序列的第i个记录。
代码:void SelectSort(List R,int n)
{ int min,i,j;
for(i=1;i<=n-1;i++)
{ min=I;
for(j=i+1;j<=n;j++)
if (R[j].key<R[min].key) min=j;
if (min!=i) swap(R[min],R[i]);
}
}
图解:
第一趟的比较,第一个分别于其他值进行比较,总是将最小的值换到第一位;第二趟的比较,第二个值分别于其后的各个值进行比较,也总是将最小的值换到第二位上,其他的都依次类推。