排序——选择排序、快速排序
知识点总结报告
知识点:
选择排序
(原理)基本思想:第i趟排序开始时,当前有序区和无序区分别为R[0...i-1]和R[i..n-1](0<=i<n-1),该趟排序是从当前无序区中选出关键字最小的元素R[k],将它与无序区的第一个元素R[i]交换,使R[0..i]和R[i+1..n-1]分别变为新的有序区和新的无序区。
因为每趟排序均使有序区中增加了一个元素,且有序区中元素的关键字均不大于无序区中元素的关键字,即第i趟排序之后R[0..i]的所有关键字均小于等于R[i+1..n-1]中的所有关键字,所以进行n-1趟排序之后R[0..n-2]的所有关键字小于等于R[n-1].key,也就是说,经过n-1趟排序之后整个表R[0..n-1]递增有序。
简单选择排序算法
void SelectSort(RecType R[ ],int n)
{ int i,j,k;
for(i=0;i<n-1;i++)
{ k=i;
for(j=i+1;j<n;j++)
if(R[j].key<R[k].key)
k=j;
if(k!=j)
swap(R[i],R[k]);
}
}
快速排序
(原理)快速排序是由冒泡排序改进而得的,它的基本思想是在待排序的n个元素中任取一个元素(通常取第一个元素)作为基准,把该元素放在适当位置后,数据序列被此元素划分为两部分。所有关键字比该元素关键字小的元素放置在前一部分,所有比它大的元素放置在后一部分,并把该元素排在这两部分的中间(称为该元素归位),这个过程称为一趟快速排序,及即一趟划分。
之后对产生的两个部分分别重复上述过程,直至每部分内只有一个元素或空为止。简而言之,每趟使表的第一个元素放入适当位置,将表一分为二,对子表按递归方式继续这种划分,直至划分的子表的长度为1或0。
一趟快速排序的划分过程partition(R,s,t)是采用从两头向中间扫描的办法,同时交换与基准元素逆序的元素。具体方法是设两个指示器i和j,它们的初值分别为指向无序区中的第一个和最后一个元素。假设无序区中元素为R[s],R[S+1],...R[t],则i的初值为s,j的初值为t,首先将R[s]移至变量tmp中作为基准,令j自位置t起向前扫描直至R[j].key<tmp.key时将R[i]移至
位置i,然后让i向后扫描直至R[i].key>tmp.key时将R[i]移至位置j,依次重复直至i=j,此时所有R[k](k=s,s+1...,i-1)的关键字都小于tmp.key,而所有R[k](k=i+1,i+2,...,t)的关键字必大于tmp.key,此时再将tmp中的元素移至位置i,它将无序区中的元素分割成R[s..i-1]和R[i+1..t],以便分别进行排序。
快速排序算法
int partition(RecType R[ ],int s,int t) //一趟划分
{ int i=s,j=t;
RecTyoe tmp=R[i]; //以R[i]为基准
while(i<j) //从两端交替向中间扫描,直至i=j为止
{ while(j>i&&R[j].key>=tmp.key)
j--; //从右向左扫描,找一个小于tmp.key的R[j]
R[i]=R[j]; //找到这样的R[j],放入R[i]处
while(i<j&&R[i].key<=tmp.key)
i++; //从左向右扫描,找一个大于tmp.key的R[i]
R[j]=R[i]; ////找到这样的R[i],放入R[j]处
}
R[i]=tmp;
return i;
}
void QuickSort(RecType R[ ],int s, int t) //对R[s..t]的元素进行快速排序
{ int i;
if(s<t) //区间内至少存在两个元素的情况
{ i=partition(R,s,t);
QuickSort(R,s,i-1); //对左区间递归排序
QuickSort(R,i+1,t); //对右区间递归排序
}
}