各种排序算法分析+实现

以前是直接用sort,对各种排序算法模模糊糊的,到了期末,无无聊聊地整理了各种常见的排序算法,顺便复习一下数据结构:)

1、直接插入排序

#define N 1005
//插入排序(稳定的排序)
//复杂度O(n^2)
//基本思想:依次将数据表中的每一个数据元素
//按关键字大小插入到以排序好的有序序列中
//方法:a[0]暂存当前的元素,依次向后比较,当大于就向后移一个位,直到不能比较时就把a[0]放入当前位置
//2011年12月11日
int a[N];
int n;
void insert_sort(int x) {
    a[0] = a[x];
    int j = x-1;
    while (a[0] < a[j]) {
        a[j+1] = a[j];
        j--;
    }
    a[j+1] = a[0];
}

int main(){
    int i,j;
    cin>>n;
    for (i=1;i<=n;i++)cin>>a[i];
    for (i=1;i<=n;i++) {
        insert_sort(i);
    }
    for (i=1;i<=n;i++)cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

2、冒泡排序

#define N 1005
//冒泡排序(稳定的排序)
//复杂度O(n^2)
//基本思想:通过对相邻的两个元素比较及其交换来达到排序的目的
//实现:需要比较n-1趟,每趟比较前n-i个数,如果前面一个比接着的后一个大就交换,可以看出这也是稳定排序
//2011年12月11日
int a[N];
int n;
void bubble_sort() {
    int i,j;
    for (i=1;i+1<=n;i++) {
        for (j=1;j<=n-i;j++) {
            if (a[j] > a[j+1]) {
                swap(a[j],a[j+1]);
            }
        }
        //for (j=1;j<=n;j++)cout<<a[j]<<" ";
        //cout<<endl;
    }
}

int main(){
    int i,j;
    cin>>n;
    for (i=1;i<=n;i++)cin>>a[i];
    bubble_sort();
    for (i=1;i<=n;i++)cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

3、直接选择排序

#define N 1005
int a[N];
int n;
//直接选择排序(不稳定的排序)
//复杂度O(n^2)
//基本思想:每一趟都要找出关键字最小(或最大)的元素
//实现:进行n-1趟,每一趟都要找出当前元素之后(包括当前元素)的最小元素,若找到就与当前元素交换
//2011年12月11日
void select_sort() {
    int i,j;
    for (i=1;i+1<=n;i++) {
        int k = i;
        for (j=i+1;j<=n;j++) {
            if (a[j] < a[k])k = j;
        }
        if (i != k) {
            swap(a[k],a[i]);
        }
    }
}

int main(){FRE;
    int i,j;
    cin>>n;
    for (i=1;i<=n;i++)cin>>a[i];
    select_sort();
    for (i=1;i<=n;i++)cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

4、快速排序

详见我的blog

#define N 1005
int a[N];
int n;
//快速排序(不稳定的排序)
//复杂度O(nlgn)
/*基本思想::通过一趟排序将要排序的数据分割成独立的两部分,
*其中一部分的所有数据都比另外一部分的所有数据都要小,
*然后再按此方法对这两部分数据分别进行快速排序,
*整个排序过程可以递归进行,以此达到整个数据变成有序序列。
*/
//实现:见我的blog——http://blog.csdn.net/leolin_/article/details/6700748
//2011年12月13日
void qk_sort1(int s,int t,int &pos) {//pos定义为引用,因为要修改s值
    int i = s;
    int j = t;
    int x = a[pos];
    while (i < j) {
        while ((i < j) && a[j] >= x) j--;
        a[i] = a[j];
        while ((i < j) && a[i] <= x) i++;
        a[j] = a[i];
    }
    a[i] = x;//因为只有在一趟处理结束后,i=j的位置才是支点元素最后的位置,所以最后才赋新值
    pos = i;//修改s值
}
void qk_sort0(int s,int t) {
    int l;
    int r;
    if (s < t) {
        l = s;
        r = t;
        qk_sort1(s,t,s);
        qk_sort0(l,s-1);//递归处理左边
        qk_sort0(s+1,r);//递归处理右边
    }
}
int main(){
    int i,j;
    cin>>n;
    for (i=1;i<=n;i++)cin>>a[i];
    qk_sort0(1,n);
    for (i=1;i<=n;i++)cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

5、堆排序

详见myblog

//堆排序(不稳定的排序)
//复杂度O(nlgn)
//实现:见我的blog——http://blog.csdn.net/leolin_/article/details/6655558
//2011年12月13日
#define N 1005
int a[N];

void sift(int k,int m) {//k表示要调整的元素在数据表中的序号,m表示最后一个数据元素在数据表中的序号
    int i,j,x;/
    bool ok = false;//ok代表是否调整完毕
    i = k;//i为双亲序号
    j = 2*i;//j为儿子序号
    x = a[k];
    while ((j<=m) && (!ok)) {
        if ((j < m) && (a[j] > a[j+1])) j++;
        if (x <= a[j]) ok = true;
        else {
            a[i] = a[j];
            i = j;
            j = 2 * i;
        }
    }
    a[i] = x;//单向移动
}
void heap_sort(int m) {
    int i,j;
    int k=m/2;
    for (i=k;i>=1;i--) {//先建堆
        sift(i,m);
    }
    for (i=m;i>=2;i--) {//这里把之前建的堆取出堆顶元素从后往前放,接着就对i-1个元素继续调整堆,所以是从大到小输出
        swap(a[1],a[i]);
        sift(1,i-1);
    }
}
int main(){
    int i,j;
    int n;
    cin>>n;
    for (i=1;i<=n;i++)cin>>a[i];
    heap_sort(n);
    for (i=1;i<=n;i++)cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

6、归并排序

详见myblog

//归并排序(稳定的排序)
//复杂度O(nlgn)
/*思想:将具有n个元素的初始序列看成是n个长度为1的有序子序列,然后进行两两归并
*得到[n/2]个长度为2的有序子序列,然后再两两归并,如此重复直到得到一个长度为n的有序序列为止
*/
//实现:见我的blog——http://blog.csdn.net/leolin_/article/details/6692979
//2011年12月13日
#define N 1005
int a[N];
int n;
void merge_sort1(int l,int mid,int r) {//l~mid表示左边的有序子序列,mid+1~r表示右边的有序子序列
    int tmp[n+2];//创建中间数组
    int i;
    int k=l;
    for (i=l;i<=mid;i++)tmp[k++] = a[i];
    for (i=r;i>mid;i--)tmp[k++] = a[i];//这样做是使得tmp数组是中间大两边小,然后比较时从两边开始比较
    int s=l,t=r;
    for (i=l;i<=r;i++) {
        if (tmp[s] < tmp[t]) a[i]=tmp[s++];
        else a[i]=tmp[t--];
    }
}
void merge_sort0(int s,int t){
    if (s==t)return ;
    int mid=(s+t)/2;
    merge_sort0(s,mid);//左边递归
    merge_sort0(mid+1,t);//右边递归

    merge_sort1(s,mid,t);//归并当前两个有序子序列
}
int main(){
    int i,j;
    cin>>n;
    for (i=1;i<=n;i++)cin>>a[i];
    merge_sort0(1,n);
    for (i=1;i<=n;i++)cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}


几种常见排序 基于比较的排序算法: 下界是 nlgn 1.1 SelectionSort:每次选出最下的元素,放在当前循环最左边的位置。 1.2 BubbleSort:每次比较相邻的两个数,使得最大的数像气泡一样冒到最右边。 1. 3 InsertionSort:每次拿起一个数,插入到它左边数组的正确位置。 1.4 QuickSort:选择一个数,作为标准,小于它的放在左边,大于它的放在右边。并把它放在中间;递归地对左右子数组进行排序实现时:1. 确定递归结束条件,初始化左右游标, 选择标准数; 2. while循环,do while实现两个游标同时向中间移动,置换; 3. 置换标准数和右边游标所指的数; 4. 递归调用,对左右子数组进行排序。 1. 5 HeapSort:用最大堆实现实现时:建堆:置换堆顶元素和最后一个元素,堆大小减少,保持新的堆为最大堆; 保持最大堆: 从底向上依次保持最大堆,从第一个父节点到根部。 1.6 MergeSort:拆分数组,递归实现排序,二路归并。用哨兵来阻止游标的越界。 线性时间运行的算法: 1.7 CountingSort: 假设数据分布在0到k之间的。对于每个输入x,确定出小于x的数的个数。假设小于x的数有17个,那么x就应该在第18个输出位置。 1. 8 Radix sort(基数排序):从最低位开始,每位采用稳定的排序算法(如计数排序)。 1.9 Bucket sort:当输入数据比较均匀时采用。 先将数据区间分为n个桶,把数据分放到对应的桶中;对桶内的数据采用插入排序;再把各个桶的排序结果串起来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值