排序总结:插入(简单和改进)、希尔、选择、冒泡、快速、堆排序、归并排序

原创 2015年07月08日 23:05:25

插入:基础的、改进的、希尔
选择:基础的、堆排序
交换:冒泡、快排及其改进
归并:将两个已经排好序的文件归并成一个有序的大文件(比较适合链表)

typedef int Item;
#define key(A) (A)
#define eq(A,B) (key(A) == key(B))
#define less(A,B) (key(A) < key(B))
#define exch(A,B) {Item t = A;A = B; B =t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
#define min(A,B) A < B ? A : B
//基础的插入排序
void simpleinsertsort(Item a[],int l,int r)
{
    int i,j;
    for(i = l+1;i <= r;i++)
        for(j = i;j > l;j--)
        compexch(a[j-1],a[j]);  //从i处往前对比,把小的移到前面!
}

//改进的插入排序
void insertsort(Item a[],int l,int r)
{
     int i,j;
     Item v;
     for(i = r;i > l;i--)
        compexch(a[i-1],a[i]);  //将最小值放在首位
     for(i = l+2;i <= r;i++)
     {
         j = i;
         v = a[i];
         while(less(v,a[j-1]))  //与当前索引值比较,比v大就将其右移,否则退出,
         {
             a[j] = a[j-1];      //只是赋值,并不交换
             j--;
         }
         a[j] = v;            //此时j+1与i之间的数都是比v大的,将v插入在j
     }
}
//希尔排序
void shellsort(Item a[],int l,int r)  //对步长的选择很重要(h要取到1)
{
      int h,i,j;
      for(h = 1;h <= (r-l)/7;h = 3*h+1);  //创建一个步长序列,最终h要取到1
      for(;h > 0;h = h/3)               //对每一个步长都要进行一次扫描排序
       for(i = l+h;i <= r;i++)         //从l+h开始:因为后面有对j-h的比较,
      {
          j = i;
          Item v = a[j];
          while(j-h >= l && less(v,a[j-h])) //这一循环与insertsort的思想一样
            {
                a[j] = a[j-h];          //只不过insert是h=1,这里的步长h可变
                j = j-h;
            }
            a[j] = v;
      }
}

//选择排序
void selectsort(Item a[],int l,int r)
{
    int i,j,Min;
    for(i = l;i < r;i++)               //当前索引左边的元素都是排好序的(最终位置)
    {
        Min = i;
        for(j = i+1;j <= r;j++)      //从左到右,记录最小元素下标,
            if(less(a[j], a[Min]))
             Min = j;
        exch(a[i],a[Min]);           //将最小元素交换到相应位置
    }
}
//堆排序
void fixDown(Item *pq,int k,int N)   //自顶向下堆化
{
    int j;
    while(2*k <= N)
    {
        j = 2*k;
        if(j < N && less(pq[j],pq[j+1]))  //找到子节点中的较大值
           j++;
        if(!less(pq[k],pq[j]))           //若较大值小于父节点就结束,否则交换子父节点
            break;
        exch(pq[k],pq[j]);
        k = j;
    }
}

void heapsort(Item a[],int l,int r)
{
    Item *pq = a;
    int k,N = r-l;
    for(k = N/2;k >= l;k--)  //将最大值交换到数组首位
        fixDown(pq,k,N);
    show(a,l,r);
    while(N > 0)
    {
        exch(pq[0],pq[N]);   //每次将首位元素(剩余数组元素中最大值)与最后的元素交换
        fixDown(pq,0,--N);   //接着数组大小-1,将剩余元素堆化,接着下一轮循环
    }
}
//冒泡排序
void bubblesort(Item a[],int l,int r) //遍历文件,依次比较相邻元素,将最小值排到前面
{
     int i,j;
     for(i = l;i < r;i++)
        for(j = r;j > i;j--)  //for(j = l+1;j <= i;j++)也可以用前面的循环
        compexch(a[j-1],a[j]);
}
//快速排序中的划分函数
int qpartition(Item a[],int l,int r)
{
    Item v = a[r];
    int i,j;
    i = l;
    j = r-1;
    for(;;)
    {
        while(less(a[i],v))  //左扫描,划分元素v左边不大于v
            i++;
        while(less(v,a[j]))  //右扫描,划分元素v右边不小于v
            {
                j--;
                if(j == l)
                    break;
            }
        if(j <= i)
            break;
        exch(a[i],a[j]);   //左扫描大于v的元素与右扫描小于v的元素交换
    }
    exch(a[r],a[i]);   //划分结束,将划分元素置换到结束位置
    return i;
}
//基本的快排:
void quicksort(Item a[],int l,int r)
{
    int i;
    if(r < l)
        return;
    i = qpartition(a,l,r);
    quicksort(a,l,i-1);
    quicksort(a,i+1,r);
}
//三路取中快排:取待排序列的首、中、尾三个元素,取大小居中的作为划分元素
void quicksortMid(Item a[],int l,int r)
{
    if(r-l <= 3)
       {
            simpleinsertsort(a,l,r);  //当数组小于某一大小时,就采用插入操作
            return;
       }
    exch(a[(l+r)/2],a[r-1]);
    compexch(a[l],a[r-1]);
    compexch(a[l],a[r]);
    compexch(a[r-1],a[r]);  //将三者中的中间元素放于r-1处,v=a[r-1]
    int i = qpartition(a,l+1,r-1); //v=a[r-1]
    quicksortMid(a,l,i-1);
    quicksortMid(a,i+1,r);
}
//三路划分快排:将待排序列分为三路:小于v、等于v、大于v
void quicksortDiv(Item a[],int l,int r)
{
     if(r <= l)
        return;
     int i,j,p,q;
     Item v = a[r];
     i = l;
     j = r;
     p = l;
     q = r-1;
     for(;;)
     {
         while(less(a[i],v)) i++;
         while(less(v,a[--j]))
            if(j == l)
              break;
            if(j <= i)
                break;
        exch(a[i],a[j]);
        if(eq(a[i],v))
            {
                exch(a[p],a[i]);   //需要对数组下标进行自加或自减时,最好与数组元素的引用分开
                p++;               //就如左边两句:先交换,然后再自加得到下一元素的下标!否则,有可能交换到相邻位置
            }
        if(eq(a[j],v))
            {
                exch(a[q],a[j]);
                q--;
            }
     }
     exch(a[i],a[r]);   //这里a[r]不能用v代替,否则a[i]处存的是v,但是a[r]处没变
     j = i-1;
     i = i+1;
     while(p > l)
        {
            p--;
            exch(a[p],a[j]);
            j--;
        }
     while(q < r-1)
        {
            q++;
            exch(a[i],a[q]);
            i++;
        }
     quicksortDiv(a,l,j);
     quicksortDiv(a,i,r);
}
//利用快排里的划分函数来寻找序列中第k个最小元素(非递归的形式、递归的调试未成功,成功后再上传)
int selectsortPar2(Item a[],int l,int r,int k)
{
   int i;
    while(r > l)
    {
       i = qpartition(a,l,r);
       if(i < k)
        l = i+1;
       if(i > k)
        r = i-1;
       if(i == k)
        break;
    }
    return a[i];
}
//归并排序:会用到大量的额外空间,如果两个待归并序列并不有序,可以先排序,再将其进行归并
void mergesort(Item c[],Item a[],int N,Item b[],int M)
{
    int i,j,k;
    for(i = 0,j = 0,k = 0;k < N+M;k++)
    {
        if(i == N)
        {
            c[k] = b[j];
            j++;
            continue;
        }
        if(j == M)
        {
            c[k] = a[i];
            i++;
            continue;
        }
        if(a[i] < b[j])
        {
            c[k] = a[i];
            i++;
        }
        else if(a[i] >= b[j])
        {
            c[k] = b[j];
            j++;
        }
    }
}

六大排序(选择,插入,冒泡,希尔,快排,堆排序)

1.实现简单选择排序、直接插入排序和冒泡排序。 2.实现希尔排序算法。 3.实现快速排序算法。 4.实现堆排序算法。 想想这么多排序方法,乍一看挺复杂,写起来还挺简单的…… #include #i...
  • martinue
  • martinue
  • 2016年06月14日 18:17
  • 896

排序算法----冒泡排序+插入排序+选择排序+快速排序+希尔排序+堆排序+归并排序+计数排序+基数排序+桶排序(c语言)

c语言实现各种排序算法
  • zlhzlh11
  • zlhzlh11
  • 2015年10月14日 15:18
  • 1600

排序算法(选择、希尔、二分插入、冒泡、直接插入、快速排序)

选择排序法                                                                                    第1趟,在待排序...
  • especialjie
  • especialjie
  • 2016年09月22日 11:21
  • 1335

五种排序方法(选择、冒泡、快排、插入、希尔)

*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Wo...
  • vcx08
  • vcx08
  • 2016年07月29日 21:40
  • 1165

各种排序算法(冒泡、选择、快排、插入、希尔、堆排、归并、计数、基数)

各种排序算法
  • wanglelelihuanhuan
  • wanglelelihuanhuan
  • 2016年05月07日 22:42
  • 3026

冒泡、插入、快速、选择排序的java实现

摘要:算法的好处什么的都不再赘述、单刀直入——直接贴出整理的几个常用的算法的基本描述、原理和java的实现过程。本篇是武功秘籍上部、下部还在酝酿中。 注:问题的引出都是对一系列可进行排序的数字进行排序...
  • chenghuaying
  • chenghuaying
  • 2014年03月05日 17:32
  • 2948

各种排序算法总结篇(快速/堆/希尔/归并)

1.快速排序 交换排序有:冒泡(选择)排序和快速排序,冒泡和选择排序的时间复杂度太高,思想很简单暂时不讨论,快速排序基于一种分治的思想,逐步地使得序列有序。 #include #include ...
  • txl16211
  • txl16211
  • 2016年04月06日 22:15
  • 2932

八大内部排序算法(上)-冒泡、直接插入、简单选择、快速

八大内部排序算法(上)冒泡、直接插入、简单选择、快速 排序分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要...
  • Dream_angel_Z
  • Dream_angel_Z
  • 2015年04月21日 16:43
  • 1895

几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)

最近决定每天学点数据结构与算法,写博客来督促自己继续学习~ 以下的每个排序的写法格式基本按照先介绍基本思想,再描述具体过程,最后是具体代码。关于复杂度等问题后续更新。如有写的不严谨的地方,欢迎指出,...
  • zouliping123
  • zouliping123
  • 2013年04月25日 15:10
  • 2031

常见经典排序算法学习总结(插入、shell、冒泡、选择、归并、快排等)

博主在学习过程中深感基础的重要,经典排序算法是数据结构与算法学习过程中重要的一环,这里对笔试面试最常涉及到的7种排序算法(包括插入排序、希尔排序、选择排序、冒泡排序、快速排序、堆排序、归并排序)进行了...
  • u010418035
  • u010418035
  • 2015年08月04日 17:53
  • 2606
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:排序总结:插入(简单和改进)、希尔、选择、冒泡、快速、堆排序、归并排序
举报原因:
原因补充:

(最多只允许输入30个字)