几大排序算法

转载请标明出处:http://i.cnblogs.com/EditPosts.aspx?postid=4711012&update=1

1.直接插入排序

思想:待排序记录R[1...n]看成两段,有序R[1...m],无序R[m+1,n],每次将无序记录插到有序记录中,直到整体有序。

// InsertSort.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include <vector>
#include <iterator>

using namespace std;

void print(int a[],int n)
{
    for (int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

void insert_sort(int a[],int n)
{
    int i,j,temp;
    for (i=1;i<n;i++)
    {
        temp=a[i];
        for (j=i-1;j>=0&&temp<a[j];j--)
        {
            a[j+1]=a[j];
        }
        a[j+1]=temp;
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
    int a[]= {7,3,5,8,9,1,2,4,6};
    cout<<"before :"<<endl;
    print(a,9);
    insert_sort(a,9);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
插入排序

2.shell排序

思想:按增量d分组排序,d每次减半,直至1

// shell_sort.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

void print(int a[],int n)
{
    for (int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

void shell_sort(int a[],int n)
{
    int d,i,j,temp;
    for (d=n/2;d>0;d=d/2)//增量控制
    {
        for(i=d;i<n;i++)//插入排序类似
        {
            temp=a[i];
            for (j=i-d;(j>=0&&a[j]>temp);j-=d)
            {
                a[j+d]=a[j];
            }
            a[j+d] = temp;
        }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[]= {7,3,5,8,9,1,2,4,6};
    cout<<"before :"<<endl;
    print(a,9);
    shell_sort(a,9);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
shell

看成改进后的插入排序

3.冒泡排序

思想:每两个一比较,n个元素比较n-1次,得到一个目标元素

// bubble_sort.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

void print(int a[],int n)
{
    for (int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

void bubble_sort(int a[],int n)
{
    int i=0;
    int j=0;
    int temp=0;
    int exchange=0;
    for (i=0;i<n-1;i++)//n-1趟
    {
        for (j=0;j<n-i-1;j++)
        {
            if (a[j+1]<a[j])
            {
                temp=a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
                exchange = 1;
            }
        }
        if (exchange!=1)//没有交换,进行下一次扫描
        {
            return;
        }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[]= {7,3,5,8,9,1,2,4,6};
    cout<<"before :"<<endl;
    print(a,9);
    bubble_sort(a,9);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
bubble_sort

4.快速排序

思想:选取第一个元素为基准,通过一趟排序将序列分为大小两部分,此时正好得到基准的正确位置。再以此对左右两部分递归划分

从右找第一个小于pivot的元素,交换;再从左找第一个大于pivot的元素,交换。。。

// bubble_sort.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

void print(int a[],int n)
{
    for (int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

void quick_sort(int a[],int low,int high)
{
    int i,j,pivot;
    if (low<high)
    {
        i=low;
        j=high;
        pivot=a[low];
        while(i<j)
        {
            while (i<j && a[j]>=pivot)--j;
            if(i<j)
            {
                a[i]=a[j];
                i++;
            }
            //a[i++]=a[j];
            while(i<j&&a[i]<pivot)++i;
            if (i<j)a[j--]=a[i];
        }
    
        a[i]=pivot;
        quick_sort(a,low,i-1);
        quick_sort(a,i+1,high);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[]= {7,3,5,8,9,1,2,4,6};
    cout<<"before :"<<endl;
    print(a,9);
    quick_sort(a,0,8);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
quick_sort
// bubble_sort.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

void print(int a[],int n)
{
    for (int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

int getMiddle(int a[],int low,int high)
{
    int i=low;
    int j=high;
    int pivot=a[low];
    while(i<j)
    {
        while (i<j && a[j]>=pivot)--j;
        if(i<j)
        {
            a[i]=a[j];
            i++;
        }
        //a[i++]=a[j];
        while(i<j&&a[i]<pivot)++i;
        if (i<j)a[j--]=a[i];
    }
    return i;
}
void quick_sort(int a[],int low,int high)
{
    if (low<high)
    {
        int middle=getMiddle(a,low,high);
        quick_sort(a,low,middle-1);
        quick_sort(a,middle+1,high);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[]= {7,3,5,8,9,1,2,4,6};
    cout<<"before :"<<endl;
    print(a,9);
    quick_sort(a,0,8);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
quick_sort2

 

// quicksort.cpp : 定义控制台应用程序的入口点。
/*
   以上给出的是最初的版本,该程序为算法导论给出的原址排序   
*/

#include "stdafx.h"
#include <iostream>

using namespace std;

void print(int a[],int size)
{
    for (int i=0;i<size;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

void exchange(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}

int partition(int a[],int p,int r)
{
    int x=a[r];
    int i=p-1;
    int j;
    for (j=p;j<=r-1;j++)
    {
        if(a[j]<x)
        {
            i++;
            exchange(a[j],a[i]);
        }
    }
    exchange(a[i+1],a[r]);
    return i;
}

void quicksort(int a[],int low,int high)
{
    int pos;
    if (low<high)
    {
        pos=partition(a,low,high);
        quicksort(a,low,pos);
        quicksort(a,pos+1,high);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[]={5,3,6,7,9,8,1,4,2};
    cout<<"before:"<<endl;
    print(a,9);
    quicksort(a,0,8);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
PARTITION

 

5.选择排序

思想:在要排序的序列中选出最小的一个与第一个交换,然后在剩下的选出次小的与第二个交换,以此类推。

// bubble_sort.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

void print(int a[],int n)
{
    for (int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

void select_sort(int a[],int n)
{
    int minValue,index;
    for (int i=0;i<n;i++)//n-1次遍历
    {
        minValue=a[i];
        index=i;
        for (int j=i;j<n;j++)
        {
            if (a[j]<minValue)//保存每次遍历的最小数和下标
            {
                minValue=a[j];
                index=j;
            }
        }
        a[index]=a[i];//把最小值和a[i]交换
        a[i]=minValue;
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    int a[]= {7,3,5,8,9,1,2,4,6};
    cout<<"before :"<<endl;
    print(a,9);
    select_sort(a,9);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
select_sort

 6.堆排序

思想:将R[1...n]看成是一棵完全二叉树的顺序存储结构,则:

1).将原始序列建成大(小)根堆;

2).将根与最后一个节点交换,输出根节点;

3).将2得到的二叉树调整为大根堆;

重复2),3);

 

/// bubble_sort.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include <iostream>
using namespace std;

int heapsize = 0;
int Left(int index){return (index<<1)+1;} //2i+1
int Right(int index){return (index<<1)+2;}//2i+2

void swap(int *a,int *b)
{
    int t;
    t = *a;
    *a= *b;
    *a= t;
}

void print(int a[],int n)
{
    for (int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}

void HeapAjustify(int a[],int index)
{
    int left = Left(index);
    int right = Right(index);
    int largest=0;//记录最大值的下标
    if ((left<=heapsize)&&(a[left]<a[index]))largest=index;
    else largest=left;
    if ((right<=heapsize)&&(a[right]>a[largest]))largest = right;
    
    if (largest!=index)//index为根的子树中根最大不是根
    {
        swap(&a[largest],&a[index]);//
        HeapAjustify(a,largest);
    }
}

void buildMaxHeap(int a[],int arrLen)
{
    heapsize = arrLen;
    for (int i=arrLen>>1;i>=0;i--)
    {
        HeapAjustify(a,i);
    }
}
void heap_sort(int a[],int aSize)
{
    buildMaxHeap(a,aSize-1);//(1)建堆
    for (int i=aSize-1;i>=1;i--)
    {                       //for(0--size){
        swap(&a[0],&a[i]);  //(2)堆输出
        heapsize--;
        HeapAjustify(a,0);  //(3)调整
    }                       // } //endfor
}


int _tmain(int argc, _TCHAR* argv[])
{
    int a[]= {7,3,5,8,9,1,2,4,6};
    cout<<"before :"<<endl;
    print(a,9);
    heap_sort(a,9);
    cout<<"after:"<<endl;
    print(a,9);
    system("pause");
    return 0;
}
heap_sort

堆是一棵完全二叉树,满足二叉树的所有性质;

对于一颗高度为h的堆,调整堆的时间为O(h);

7.归并排序

自底向上:将序列看成是n个长度为1的子序列,两两归并。

自顶向下:将序列一分为二,然后递归求解

     对两堆排好序且正面朝上的扑克,每次从表面选择较小一张,直到所有牌取完。

 1 // merge_sort.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <iostream>
 6 
 7 using namespace std;
 8 
 9 void print(int a[],int n)
10 {
11     for (int i=0;i<n;i++)
12     {
13         cout<<a[i]<<" ";
14     }
15     cout<<endl;
16 }
17 void merge(int a[],int temp[],int llow,int rlow,int rend)//利用额外的数组来组合
18 {
19     int NumEle = rend-llow+1;
20     int lend = rlow-1;
21     int position=llow;
22     while (llow<=lend&&rlow<=rend)
23     {
24         if (a[llow]<=a[rlow])temp[position++]=a[llow++];
25         else temp[position++]=a[rlow++];
26     }
27     while(llow<=lend)temp[position++]=a[llow++];
28     while(rlow<=rend)temp[position++]=a[rlow++];
29     for (int i=0;i<NumEle;i++,rend--)
30         a[rend]=temp[rend];
31 
32 }
33 void merge_sort_1(int a[],int temp[],int low,int high)//找中点,分别递归
34 {
35     if(low>=high)return;
36     int middle = (low+high)/2;
37     merge_sort_1(a,temp,low,middle);
38     merge_sort_1(a,temp,middle+1,high);
39     merge(a,temp,low,middle+1,high);
40 }
41 
42 
43 void merge_sort(int a[],int size)//申请空间
44 {
45     int *temp = NULL;
46     temp = new int[size];
47     if (temp!=NULL)
48     {
49         merge_sort_1(a,temp,0,size-1);
50         delete []temp;
51     }
52 
53 }
54 
55 int _tmain(int argc, _TCHAR* argv[])
56 {
57     int a[]={7,3,2,6,8,4,5,9,1};
58     print(a,9);
59     merge_sort(a,9);
60     print(a,9);
61     system("pause");
62     return 0;
63 }
merge_sort

*分治法:对于结构是递归的算法,将原问题分解为多个规模小且类似原问题的子问题,递归求解他们,再将它们的解组合起来构成原问题的解。

采用递归式来描述递归算法的划分,求解得到简单递归的渐进界(主方法)。还有递归树法,两种常用分析法

 

8.计数排序

思想:对于每个输入元素x,确定比它小的数,就可以将它放到正确的位置上了。计数排序假设输入数据都属于一个小区间内的整数。

 1 // CountSort.cpp : 定义控制台应用程序的入口点。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <iostream>
 6 #include <memory>
 7 
 8 using namespace std;
 9 
10 void print(int a[],int len)
11 {
12     for (int i=0;i<len;i++)
13     {
14         cout<<a[i]<<" ";
15     }
16     cout<<endl;
17 }
18 
19 int findmax(int a[],int size)
20 {
21     int max=a[0];
22     for (int i=1;i<size;i++)
23     {
24         if (a[i]>max)max=a[i];
25     }
26     return max;
27 }
28 
29 void countsort(int a[],int len,int &max)
30 {
31     int* b=(int *)malloc(len*sizeof(int));
32     int* c=(int *)malloc((max+1)*sizeof(int));
33     memset(b,0,len*sizeof(int));
34     memset(c,0,(max+1)*sizeof(int));
35     /*
36     这里for有点问题,i应该从0开始,但是结果有点误差,c[]正确.
37     从1开始结果正确,但c[]错,且说不通。
38     */
39     for (int i=0;i<len;i++)
40         c[a[i]]=c[a[i]]+1;
41     //c[] contains the number of elements equal to i.
42     print(c,max+1);
43 
44     for (int j=1;j<=max;j++)
45         c[j]=c[j]+c[j-1];
46     //c[] now contains the number of elements less then or equal to i.
47     print(c,max+1);
48 
49     for (int k=len-1;k>=0;--k)
50     {
51         /*
52          1st:k=7,a[k] is the value of array;
53              c[a[k]] is the number of elements that <= a[k];
54              b[c[a[k]]] means a[k] was put to array b, its 
55              position is c[a[k]].because there are c[a[k]]-1
56              elements before it.
57          ...
58         */
59         b[c[a[k]]]=a[k];
60         c[a[k]]-=1;
61     }
62     cout<<"after:"<<endl;
63     print(b,len);
64     cout<<endl;
65     free(b);
66     free(c);
67 }
68 
69 int _tmain(int argc, _TCHAR* argv[])
70 {
71     int a[]={2,5,3,0,2,3,0,3};
72     cout<<"before:"<<endl;
73     print(a,8);
74 
75     int max=findmax(a,8);
76     countsort(a,8,max);
77     system("pause");
78     return 0;
79 }
View Code

总时间代价为theta(n+k),当k=theta(n)时,运行时间为theta(n).它不是比较排序,所以下界由于n*(lgN)。稳定排序。

 

 

9.基数排序

基数排序是通过“分配”和“收集”过程来实现排序

RADIX_SORT(A,d)

for i <- 1 to d

  do use a stable sort to sort array A on digit i

 

// radix_sort.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;

void print(int a[],int size)
{
    for (int i=0;i<size;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}



int findmax(int a[],int &size)
{
    int max=a[0];
    for (int i=1;i<size;i++)
    {
        if (a[i]>max)max=a[i];
    }
    return max;
}
// 算出数的位数
int ele_digit(int element)
{
    int digit=0;
    do 
    {
        element/=10;
        digit++;
    } while (element!=0);
    return digit;
}

int kth_digit(int number,int kth)
{
    number/=pow(10.0,kth);//砍掉前 kth-1 位
    return number%10;
}
/*
输入元素位数大小不确定,就要求最大数的位数
*/
void radix_sort(int a[],int size)
{
    int *temp[10];
    /*
    指针数组,每一个指针指向一个数组.因为个位数一般是从0-9,所以
    这里为10
    */
    int count[10]={0,0,0,0,0,0,0,0,0,0};//记录每个箱子装多少个元素
    int max=findmax(a,size);
    int maxdigit=ele_digit(max);//得到最大数的位数
    for (int i=0;i<10;i++)//初始化temp,是二维数组
    {
        temp[i]=(int *)malloc(size*sizeof(int));//每个temp变量指向一个6个元素的数组
        memset(temp[i],0,size*sizeof(int));
    }
     for (int i=0;i<maxdigit;i++)//对a[]遍历maxdigit次
     {
        //memset(count,0,size*sizeof(int));
        for (int j=0;j<size;i++)//记录元素个数
        {
            int xx=kth_digit(a[j],i);//返回number的第k位数
            temp[xx][count[xx]]=a[j];//此处有问题,我调试不出来。哪位仁兄帮帮忙
            count[xx]++;//当前处理位相同的数++
        }
        int index=0;
        for (int j=0;j<10;j++)//回收
        {
            for (int k=0;k<count[j];k++)
            {
                a[index++]=temp[j][k];
            }
        }

     }
     for (int i=0;i<10;i++)
     {
         free(temp[i]);
     }
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a[]={22,32,19,53,47,29};
    cout<<"before:"<<endl;
    print(a,6);
    radix_sort(a,6);
    cout<<"after:"<<endl;
    print(a,6);
    system("pause");
    return 0;
}
View Code

 

posted @ 2015-08-28 14:35  lp3318  阅读(289)  评论(0编辑  收藏  举报