排序

基本概念

<1>内部排序,外部排序

<2>内部排序:插入排序,选择排序(直接选择和堆排序),交换排序(冒泡和快速排序),归并排序和分配排序

 

直接插入排序

 /*对顺序表R中的记录R[1..n]按递增序进行插入排序,R[0]为哨兵*/
void lnsertSort(SeqList &R, int n)
{    
    int i,j;
    for(i=2; i<=n; i++)            //依次插入R[2],…,R[n],有序序列R[1..i-1],无序序列R[i..n]
    {
        if(R[i].key<R[i-1].key)   //若R[i].key大于R[i-1].key,则R[i]应在原有位置上,否则插入有序序列中
        {
            R[0] = R[i];           //保存R[i]的副本
            j = i-1; 
/*从右向左在有序区R[1..j]中查找R[i]的插入位置,并将大于R[i]的关键字后移*/ while(R[0].key<R[j].key) //当R[i].key≥R[j].key时终止 { R[j+1] = R[j]; j-- ; } R[j+1] = R[0]; //R[i]插入到正确的位置上 } } }

 

冒泡排序

算法:从无序区底部向上一次比较两个关键字的大小,若R[j+1].key<R[j].key,交换这两个记录。扫描i次后有序区为R[1..i-1]

/*R[l..n]是待排序的文件,采用自下向上扫描,对R做冒泡排序*/
void BubbleSort(SeqList &R)
{ 
    int i,j;
    Boolean exchange;    //交换标志
    for(i=1; i<n; i++)        //最多做n-1趟排序
    { 
        exchange=FALSE;       //本趟排序开始前,交换标志应为假
        for(j=n-1; j>=i; j--) //对当前无序区R[i..n]自下向上扫描,有序区为R[1..i-1]
            if(R[j+1].key < R[j].key)
            {
                R[0]=R[j+1]; //R[0]不是哨兵,仅做暂存单元
                R[j+1]=R[j];
                R[j]=R[0];
                exchange=TRUE; //发生了交换,故将交换标志置为真
            }
        if(!exchange) return;  //本趟排序未发生交换,说明该序列已经是有序的,则提前终止算法          
    } //endfor(外循环)
} //BubbleSort

 

快速排序

算法:<1>划分:在Partition函数中实现。在R[low,high]中任选一个记录作为基准pivot,

划分的关键是找出基准所在的位置pivotpos(pivot=R[pivotpos],且low≤pivotpos≤high),并且有R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys。

一次划分过程中,具体变化情况【参见动画演示】 

<2>求解:通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

/*对R[low..high]快速排序*/
void QuickSort(SeqList &R,int low,int high)
{ 
    int pivotpos; //划分后的基准记录的位置
    if(low<high)  //仅当区间长度大于1时才须排序
    {
        pivotpos=Partition(R, low, high);   //对R[low..high]做划分
        QuickSort(R, low, pivotpos-1);      //对左区间递归排序
        QuickSort(R, pivotpos+1, high);     //对右区间递归排序
    }
} //QuickSort

/*调用Partition(R,low,high)时,对R[low..high]做划分,并返回基准记录的位置*/
int Partition(SeqList &R, int i, int j)
{
    ReceType pivot=R[i];   //用区间的第1个记录作为基准 
    while(i<j)             //从区间两端交替向中间扫描,直至i=j为止
    { 
        while(i<j && R[j].key >= pivot.key) j--;//pivot相当于在位置i上,从右向左扫描,查找第1个关键字小于pivot.key的记录R[j]
        if(i<j) R[i++]=R[j];                //交换后,小于pivot.key的记录在pivot的左边,i加1
        while(i<j && R[i].key <= pivot.key) i++;//pivot相当于在位置j上,从左向右扫描,查找第1个关键字大于pivot.key的记录R[i]      
        if(i<j) R[j--]=R[i];                  //表示找到了R[i],使R[i].key>pivot.key,相当于交换R[i]和R[j],交换后j指针减1       
    } //endwhile
    R[i]=pivot; //基准记录已被最后定位
    return i;
} //partition

 

posted @ 2014-11-11 08:45  suo_suo  阅读(132)  评论(0编辑  收藏  举报