算法与数据结构--直接插入排序算法

  下午温习了一下排序算法。突然感觉,过完年挺久没写代码,有点生疏,还是之前没有掌握的很牢固(以下例子都是从小到大排)。

  一共有五类内部排序方法(插入排序、交换排序、选择排序、归并排序和基数排序),那现在说的直接插入排序是插入排序算法中的一类,还有一种高级的插入排序是希尔排序。本来数据结构就学得不好,希尔排序就是懵了(尽管喷吧)。直接插入排序是一种简单的插入排序算法,其基本思路是:依次把待排序的记录逐一按其关键字的大小插入到一个已经排好序的有序序列中去,直到所有的记录插完为止,得到一个新的有序序列。

  直接插入排序算法思路:

  1. 设置监视哨r[0],将待插入记录的值赋给r[0]。
  2. 设置开始查找的位置j。
  3. 在数组中进行搜索,搜索中将第j个记录后移,直至r[0].key>=r[j].key为止。
  4. 将r[0]插入在r[j+1]的位置上。

  代码清单:

 1 void zjInsert(typedef r[],int n)

 2 {

 3       int i,j;  

 4       for(i=2;i<=n;i++)   /*从第二个记录开始插入*/

 5       {

 6            r[0]=r[i];

 7            j=i-1;

 8            while(r[0].key<r[j].key)

 9            {

10                 r[j+1]=r[j];

11                 j--;             

12            }

13            r[j+1]=r[0];

14       }  

15 }    

  交换排序:交换排序是通过两两比较待排序记录的关键值,交换不满足顺序的那些偶对,直到全部满足为止。交换排序中有两种比较常用:冒泡排序和快速排序

  冒泡排序的基本思路:先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序(即r[1].key>r[2].key),则交换两个记录,然后比较第二个记录和第三个记录的关键字,若为逆序,又交换两个记录,如此下去,直至第n个记录和第n-1个记录的关键字进行比较为止,这样就完成了第一趟冒泡排序,其结果就是关键字最大的记录被安置到第n个记录的位置。然后进行第二轮冒泡排序,直至全部为顺序。

  算法思路:

  1. 第一重循环进行n-1次趟排序,k=0;
  2. 第二重循环是在进行第i趟排序时进行n-i次两两比较,若为逆序,交换并使k值增加,找出该趟的最大值放在第n-i+1位置上,继续下一趟排序;比较途中,若顺序,则无记录交换,k=0,退出整个排序循环。

  代码清单:

void BubbleSort(typedef r[],int n)

{

    int i,j,k;

    typedef x;

    i=1;

    k=1;

    while((i<n)&&(k>0))  

    {

       k=0;

       for(j=1;j<=n-i;j++)

       {

         if(r[j+1].key<r[j].key)

         {

            k++;

            x=r[j];

            r[j]=r[j+1];

            r[j+1]=x;

         } 

       }
   i++; } }

  选择排序是指每次从待排序的记录中选出关键字值最小(或最大)的记录,顺序放在已排序的子序列的后面,直到全部排完。选择排序主要包括简单选择排序和堆排序两种。

对待排序的序列进行n-1趟扫描,第i趟扫描选出剩下的n-i+1个记录中关键字值最小的记录和第i个记录互相交换。第一次待排序的空间为r[1]~r[n],经过选择和交换后,r[1]中存放最小的记录;第二次待排序的区间为r[2]~r[n],经过选择和交换后,r[2]存放次小的记录,依次类推,最后,形成r[1..n]成为有序序列。

  算法思路:

  1. 查找待排序序列中最小的记录,并将它和该区间第一个记录交换。
  2. 重复步骤1直到第n-1次排序后结束。

  代码清单:

void jdSort(typedef r[], int n)

{

     int i,j,k;

     typedef x;

     for(i=1;i<n;i++)

    {

         k=i;

         for(j=i+1;j<n;j++)

         {

              if(r[j].key<r[k].key)

              {

                    k=j;

              }

         }

         if(i!=k)

        {

             x=r[i];

             r[i]=r[k];

             r[k]=x;

        }

    }

}            

 ps:另外考虑到快速排序也是重点,是舒服交换排序的一类,也写一下关于快速排序的。

  基本思路:在待排序的n个记录中任选一个记录,通常取第一个记录,以该记录的关键字为基准,用交换的方法将所有的记录分成两部分,所有关键字比它小的记录均排在它之前,所有关键字比它大的记录都排在它以后,该基准记录在两部分中间,该位置为该基准记录的最终位置,它不再参加以后的排序,这就完成了一趟排序。然后对所分的前后两部分分别重复上面的方法,直到每部分内只有一个记录为止,排序结束。

  算法思路:设待排序记录存于r[t],r[t+1],...r[w]中,设置两个变量i和j,他们的初值分别是t和w,设基准记录x为第一个记录r[t]。排序开始时,先从j所指示的位置起向前扫描,当x.key>r[j].key时,交换r[i]和r[j],使关键字值比基准记录的关键字值小的记录交换到前面;然后从i所指示的位置起向后扫描,直到x.key<r[i].key,交换r[i]和r[j],使关键字比基准记录的关键字值大的记录交换到后面。重复着两步直至i=j为止。

 1 void QuickSort(typedef r[ ],int low,int high)

 2 {

 3     int pivotpos;

 4     if(low<high)

 5     {

 6      pivotpos=Partition(r[ ],low.high);

 7      QuickSort(r[ ],low,pivotpos-1);

 8      QuickSort(r[ ],pivotpos+1,high);       

 9     }

10 }

11 int Partition(typedef r[ ],int i,int j)    

12 {

13      typedef x=r[i];

14      while(i<j)

15     {

16         while(i<j && r[j].key>=x.key)  

17         {

18             j--;

19         }

20         if(i<j)

21        {

22            r[i]=r[j] ;

23            i++; 

24        }

25        while(i<j && r[i]<=x.key)

26        {

27           i++;

28        }

29        if(i<j)

30        {

31            r[j]=r[i];

32            j--;

33        }

34     }

35     r[i]=x;

36     return i;

37 }

 

你可能感兴趣的:(数据结构)