数据结构程序设计--排序综合问题

目录

1.课题要求

2.课题分析

3.源代码


1.课题要求

设计程序,利用随机函数产生20000个随机整数(1~100000), 完成下面功能:

(1)对这些数分别进行直接插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序2-路归并排序、链式基数排序,并把排序结果保存到文件中。

(2) 分析上述排序算法的性能(以运行程序所花费的时间为准进行对比),找出较快的排序方法。

(3)计算并输出所选排序算法中比较的次数和数据移动的次数。

(4)若排序的整数增加到100000个、100000000个,排序结果有什么变化,请分析并验证。

2.课题分析

这一课题主要考查我们对所有排序方法的应用,10大经典排序的互相结合,本质并不难,首先,先简单地介绍一下10大经典排序。

(1)冒泡排序

冒泡排序是我们最早接触编程的时候所接触的第一个排序方法,它的时间复杂度最坏为O(n2),又称为"沉底法",每次交换相邻的两个位置,如果前面的数比后面的数大,那么就交换他们,迭代n-1次就可以确定每一个数的位置。

i∈[0,N-1)               //循环N-1遍
   j∈[0,N-1-i)           //每遍循环要处理的无序部分
     swap(j,j+1)          //两两排序(升序/降序)

(2)选择排序

选择排序也是我们常用的排序方法,每次都从无序区中选择一个最小的数放在有序区的相应的位置。

for(int i=1;i<=n-1;i++) //n-1趟
    {
        int min=i;
        for(int j=i+1;j<=n;j++)//每次从当前位置向后找无序区中一个最小的值
            if(q[j]<q[min]) min=j;
        swap(q[i],q[min]);
    }

(3)快速排序

有关详细分析请看我之前写的一篇文章Algorithm(基础+提高+Top+杂题)

(4)归并排序

有关详细分析请看我之前写的一篇文章Algorithm(基础+提高+Top+杂题)

(5)堆排序

有关详细分析请看我之前写的一篇文章Algorithm(基础+提高+Top+杂题)

(6)直接插入排序

和选择排序的思路大致相同,但是不同的是直接插入排序是依次从无序区中选择一个数,然后通过在有序区中进行比较找到相应的位置,而选择排序每次则是总无序区中找到一个最小值,直接插入有序区的后面即可。

for(int i=2;i<=n;i++)
        if(q[i]<q[i-1])
        {
            int temp=q[i],j;
            for(j=i-1;j>=1&&temp<q[j];j--) q[j+1]=q[j];
            q[j+1]=temp;
        }

(7)折半插入排序

对直接插入排序的优化,每次在有序区用二分法找到相应的位置。

void mid_sort(int q[],int n)
{
    for(int i=2;i<=n;i++)
    {
        q[0]=q[i];
        int l=1,r=i-1;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if(q[mid]>q[0]) r=mid-1;
            else l=mid+1;
        }
        for(int j=i-1;j>=r+1;--j)
            q[j+1]=q[j];
        q[r+1]=q[0];
    }
}

(8)希尔排序

找到一个增量,每次对增量区间进行排序,如1,3,5/2,4,6

void shell_sort(int q[],int n)
{
    int j=n;
    while(j>1)
    {
        j=j/3+1;
        for(int i=1;i<=n-j;i++)
        {
            int r=i,t=q[r+j];
            while(r>=1)
                if(t<q[r]) q[r+j]=q[r],r-=j;
                else break;
            q[r+j]=t;
        }
    }
}

(9)桶排序

把数分成多个桶,如10~15内的数是一个桶,16~20......,每次对桶内元素进行排序,最后合并桶。

void bucket_sort(int q[],int n)
{
    int min=INF,max=-INF;
    for(int i=1;i<=n;i++)
    {
        if(q[i]<min) min=q[i];
        if(q[i]>max) max=q[i];
    }

    int count=(max-min)/n+1;

    vector<vector<int>> a;//大桶

    for(int i=1;i<=count;i++)
    {
        vector<int> b;
        a.push_back(b);//每个小桶
    }

    for(int i=1;i<=n;i++)
    {
        int num=(q[i]-min)/n;
        a[num].push_back(q[i]);
    }

    for(int i=0;i<count;i++) sort(a[i].begin(),a[i].end());

    int k=1;

    for(int i=0;i<count;i++)
        for(int j=0;j<a[i].size();j++)
            q[k++]=a[i][j];
}

3.源代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stdlib.h>
using namespace std;

const int N=1e6+10,INF=0x3f;
int q[N];
int tmp[N];
int n;
int siz;

//快速排序
void quick_sort(int q[],int l,int r)
{
    if(l>=r) return ;
    int x=q[l+r>>1],i=l-1,j=r+1;
    while(i<j)
    {
        do i++;while(q[i]<x);
        do j--;while(q[j]>x);
        if(i<j) swap(q[i],q[j]);
    }
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
}

//归并排序
void merge_sort(int q[],int l,int r)
{
    if(l>=r) return ;
    int mid=l+r>>1;
    merge_sort(q,l,mid);
    merge_sort(q,mid+1,r);
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r)
        if(q[i]<q[j]) tmp[k++] = q[i++];
        else tmp[k++] = q[j++];
    while(i<=mid ) tmp[k++] = q[i++];
    while(j<=r) tmp[k++] = q[j++];
    for(i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
}

//直接插入排序
void insert_sort(int q[],int n)
{
    for(int i=2;i<=n;i++)
        if(q[i]<q[i-1])
        {
            int temp=q[i],j;
            for(j=i-1;j>=1&&temp<q[j];j--) q[j+1]=q[j];
            q[j+1]=temp;
        }
}

//冒泡排序
void down_sort(int q[],int n)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n-i;j++)
            if(q[j]>q[j+1]) swap(q[j],q[j+1]);
}

void down(int u)
{
    int t=u;
    if(2*u<=siz&&q[2*u]<q[t]) t=2*u;
    if(2*u+1<=siz&&q[2*u+1]<q[t]) t=2*u+1;
    if(t!=u)
    {
        swap(q[t],q[u]);
        down(t);
    }
}

//堆排序
void heap_sort(int q[],int n)
{
    siz=n;
    for(int i=n/2;i>=1;i--) down(i);
    printf("排序后的结果为:");
    for(int i=1;i<=n;i++)
    {
        cout<<q[1]<<" ";
        q[1]=q[siz];
        siz--;
        down(1);
    }
}

//折半插入排序
void mid_sort(int q[],int n)
{
    for(int i=2;i<=n;i++)
    {
        q[0]=q[i];
        int l=1,r=i-1;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if(q[mid]>q[0]) r=mid-1;
            else l=mid+1;
        }
        for(int j=i-1;j>=r+1;--j)
            q[j+1]=q[j];
        q[r+1]=q[0];
    }
}

//希尔排序
void shell_sort(int q[],int n)
{
    int j=n;
    while(j>1)
    {
        j=j/3+1;
        for(int i=1;i<=n-j;i++)
        {
            int r=i,t=q[r+j];
            while(r>=1)
                if(t<q[r]) q[r+j]=q[r],r-=j;
                else break;
            q[r+j]=t;
        }
    }
}

//简单选择排序
void select_sort(int q[],int n)
{
    for(int i=1;i<=n-1;i++) //n-1趟
    {
        int min=i;
        for(int j=i+1;j<=n;j++)//每次从当前位置向后找一个最小的值
            if(q[j]<q[min]) min=j;
        swap(q[i],q[min]);
    }
}

//桶排序
void bucket_sort(int q[],int n)
{
    int min=INF,max=-INF;
    for(int i=1;i<=n;i++)
    {
        if(q[i]<min) min=q[i];
        if(q[i]>max) max=q[i];
    }

    int count=(max-min)/n+1;

    vector<vector<int>> a;//大桶

    for(int i=1;i<=count;i++)
    {
        vector<int> b;
        a.push_back(b);//每个小桶
    }

    for(int i=1;i<=n;i++)
    {
        int num=(q[i]-min)/n;
        a[num].push_back(q[i]);
    }

    for(int i=0;i<count;i++) sort(a[i].begin(),a[i].end());

    int k=1;

    for(int i=0;i<count;i++)
        for(int j=0;j<a[i].size();j++)
            q[k++]=a[i][j];
}

void print()
{
    for(int i=1;i<=n;i++) cout<<q[i]<<" ";
}

void menu()
{
    puts("**********排序综合问题**********");
    puts("**********1.快速排序  **********");
    puts("**********2.归并排序  **********");
    puts("**********3.直接插入排序*********");
    puts("**********4.冒泡排序  **********");
    puts("**********5.堆排序    **********");
    puts("**********6.折半插入排序*********");
    puts("**********7.希尔排序   **********");
    puts("**********8.简单选择排序**********");
    puts("**********9.桶排序    ***********");
}

int main()
{
    while(1)
    {
        cout<<"请输入个数:";
        scanf("%d",&n);
        printf("请输入%d个数:",n);
        for(int i=1;i<=n;i++) scanf("%d",&q[i]);
        menu();
        cout<<"请输入一个序号:";
        int op;
        cin>>op;
        if(op==1) 
        {
            quick_sort(q,1,n);
            printf("排序后的结果为:");
            print();
        }
        else if(op==2)
        {
            merge_sort(q,1,n);
            printf("排序后的结果为:");
            print();
        }
        else if(op==3)
        {
            insert_sort(q,n);
            printf("排序后的结果为:");
            print();
        }
        else if(op==4)
        {
            down_sort(q,n);
            printf("排序后的结果为:");
            print();
        }
        else if(op==5)
        {
            heap_sort(q,n);
        }
        else if(op==6)
        {
            mid_sort(q,n);
            printf("排序后的结果为:");
            print();
        }
        else if(op==7)
        {
            shell_sort(q,n);
            printf("排序后的结果为:");
            print();
        }
        else if(op==8)
        {
            select_sort(q,n);
            printf("排序后的结果为:");
            print();
        }
        else if(op==9)
        {
            bucket_sort(q,n);
            printf("排序后的结果为:");
            print();
        }
        else printf("序号错误!\n");
        puts("");
        system("pause");
        system("cls");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值