冒泡排序

 

1  排序思想

依次比较相邻的两个记录的关键字,若两个记录是反序的(即前一个记录的关键字大于后前一个记录的关键字),则进行交换,直到没有反序的记录为止。

① 首先将L->R[1]与L->R[2]的关键字进行比较,若为反序(L->R[1]的关键字大于L->R[2]的关键字),则交换两个记录;然后比较L->R[2]与L->R[3]的关键字,依此类推,直到L->R[n-1]与L->R[n]的关键字比较后为止,称为一趟冒泡排序,L->R[n]为关键字最大的记录。

②  然后进行第二趟冒泡排序,对前n-1个记录进行同样的操作。

    一般地,第i趟冒泡排序是对L->R[1 … n-i+1]中的记录进行的,因此,若待排序的记录有n个,则要经过n-1趟冒泡排序才能使所有的记录有序。

 

#define FALSE 0

#define TRUE 1

void Bubble_Sort(Sqlist *L)

         int j ,k , flag ;

         for (j=0; j<L->length; j++)       /*   共有n-1趟排序   */

         { 

                   flag=TRUE ;

                   for (k=1; k<=L->length-j; k++)   /*   一趟排序   */

              if (LT(L->R[k+1].key, L->R[k].key ) )

           {  

                            flag=FALSE ;

                            L->R[0]=L->R[k] ;

                L->R[k]=L->R[k+1] ;

                L->R[k+1]=L->R[0] ; 

         }

               if  (flag==TRUE)  break ;

         }

}

故时间复杂度:T(n)=O(n²)

空间复杂度:S(n)=O(1)

 

快速排序

1  排序思想

通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录进行下一趟排序,以达到整个序列有序。

2  排序过程

设待排序的记录序列是R[s…t] ,在记录序列中任取一个记录(一般取R[s])作为参照(又称为基准或枢轴),以R[s].key为基准重新排列其余的所有记录,方法是:

         ◆ 所有关键字比基准小的放R[s]之前;

         ◆ 所有关键字比基准大的放R[s]之后。

以R[s].key最后所在位置i作为分界,将序列R[s…t]分割成两个子序列,称为一趟快速排序。

3  一趟快速排序方法

从序列的两端交替扫描各个记录,将关键字小于基准关键字的记录依次放置到序列的前边;而将关键字大于基准关键字的记录从序列的最后端起,依次放置到序列的后边,直到扫描完所有的记录。

设置指针low,high,初值为第1个和最后一个记录的位置。

设两个变量i,j,初始时令i=low,j=high,以R[low].key作为基准(将R[low]保存在R[0]中) 。

① 从j所指位置向前搜索:将R[0].key与R[j].key进行比较:

         ◆  若R[0].key≤R[j].key :令j=j-1,然后继续进行比较, 直到i=j或R[0].key>R[j].key为止;

         ◆ 若R[0].key>R[j].key :R[j]ÞR[i],腾空R[j]的位置, 且令i=i+1;

② 从i所指位置起向后搜索:将R[0].key与R[i].key进行比较:

         ◆ 若R[0].key≥R[i].key :令i=i+1,然后继续进行比较, 直到i=j或R[0].key<R[i].key为止;

         ◆ 若R[0].key<R[i].key :R[i]ÞR[j],腾空R[i]的位置, 且令j=j-1;

①      重复①、②,直至i=j为止,i就是R[0](基准)所应放置的位置。

 

4  一趟排序示例

       设有6个待排序的记录,关键字分别为29, 38, 22, 45, 23, 67,一趟快速排序的过程如图10-7所示。

 

 

⑴  一趟快速排序算法的实现

int  quick_one_pass(Sqlist  *L , int low, int high)

         int i=low, j=high ;

         L->R[0]=L->R[i] ;       /*   R[0]作为临时单元和哨兵  */

         do

         {  

                   while (LQ(L->R[0].key, L->R[j].key)&&(j>i))

                       j-- ;

                   if  (j>i) 

                   { 

                            L->R[i]=L->R[j] ;

                            i++;  

                   }

                   while (LQ(L->R[i].key, L->R[0].key)&&(j>i))

                      i++ ;

                   if  (j>i) 

                   { 

                            L->R[j]=L->R[i] ;

                            j--;  

                   }

         } while(i!=j) ;    /*   i=j时退出扫描  */

         L->R[i]=L->R[0] ;

         return(i) ;

}

 

⑵  快速排序算法实现

        当进行一趟快速排序后,采用同样方法分别对两个子序列快速排序,直到子序列记录个为1为止。

① 递归算法

void  quick_Sort(Sqlist  *L , int low, int high)

         int k ;

         if  (low<high)

         { 

                   k=quick_one_pass(L, low, high);

                   quick_Sort(L, low, k-1);

                   quick_Sort(L, k+1, high);

         }     /*   序列分为两部分后分别对每个子序列排序   */

}

 

②  非递归算法

# define  MAX_STACK  100

void  quick_Sort(Sqlist  *L , int low, int high)

         int k , stack[MAX_STACK] ,  top=0;

         do

         { 

                   while  (low<high)

                   { 

                            k=quick_one_pass(L,low,high);

                        stack[++top]=high ; 

                            stack[++top]=k+1 ;

          /*  第二个子序列的上,下界分别入栈  */

                        high=k-1 ; 

                   }

                   if (top!=0)

                 { 

                            low=stack[top--] ;

                            high=stack[top--] ; 

                   }

         }while (top!=0&&low<high) ;

}

 

快速排序的平均时间复杂度是:T(n)=O(n㏒2n)

快速排序的空间复杂度是:S(n)=O(㏒2n)

从排序的稳定性来看,快速排序是不稳定的。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值