数据结构实验:多种排序实践

7-1 排序 (25分)

给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。

本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据1:只有1个元素;

  • 数据2:11个不相同的整数,测试基本正确性;

  • 数据3:103个随机整数;

  • 数据4:104个随机整数;

    数据5:105个随机整数;

    数据6:105个顺序整数;

    数据7:105个逆序整数;

    数据8:105个基本有序的整数;

    数据9:105个随机正整数,每个数字不超过1000。

    输入格式:

    输入第一行给出正整数N(≤105),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。

    输出格式:

    在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。

    输入样例:

    11
    4 981 10 -17 0 -20 29 50 8 43 -5

    输出样例:

    -20 -17 -5 0 4 8 10 29 43 50 981

方法1:简单粗暴STLsort+vector AC代码总计需要2分钟

直接使用STL sort+vector

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


vector<int> data;


int main()
{
    int N, i;
    cin >> N;
    for (int j = 0; j < N; j++)
    {
        cin >> i;
        data.push_back(i);
    }
    sort(data.begin(), data.end());
    vector<int>::iterator it;
    for (it = data.begin(); it != data.end() - 1; it++)
        cout << *it << ' ';
    cout << *it;
}

这个方法可以看出,STL确实是一个强大的高效算法模板库。

b34e769aeeda3e84ce09defad6654240.png

方法二:快速排序

采用快速排序,根据理论我们知道它是一定能够在要求的时间内完成排序任务的。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


vector<int> Data;


int Partition(int low,int high)
{
  int pivotloc;
  pivotloc = Data[low];
  while(low<high)
  {
    while(low<high && Data[high]>=pivotloc)high--;
    Data[low] = Data[high];
    while(low<high && Data[low]<=pivotloc)low++;
    Data[high] = Data[low];
  }
  Data[low] = pivotloc;
  return low;


}
void QSort(int low,int high)
{  
    int pivotloc;
    if(low < high)
    {
        pivotloc = Partition(low,high);
        QSort(low,pivotloc-1);
        QSort(pivotloc+1,high);
    }
}


int main()
{
    int N,i;
    cin >> N;
    for(int j=0;j<N;j++)
    {
        cin>>i;
        Data.push_back(i);
    }
    QSort(0,N-1);
    vector<int>::iterator it;
    for(it = Data.begin();it != Data.end()-1;it++)
        cout << *it << ' ';
    cout << *it;
}

4e764ed6f857e5f86ae31a905ac2aa96.png

方法三:希尔排序

希尔排序,我采用手工给出delta序列的方法,在最后时间上,竟然超过了前两个算法。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


vector<int> Data;


void Shellinsert(int d)
{
  for(int i = d; i < Data.size(); i++)
  {
    if(Data[i] < Data[i-d])
    {
      int j, tmp = Data[i];
      for(j = i-d; j >= 0 && Data[j] >= tmp; j -= d);//循环让j停留在待插入位置
      j += d;//插入位置
      for(int k = i; k != j; k -= d)Data[k] = Data[k-d];//后移 
      Data[j] = tmp;//插入     
    }
  } 
}


void ShellSort()
{
  int a[11] = {107, 93, 79, 51, 47, 37, 29, 11, 7, 3, 1};
  for(int i = 0 ; i < 11 ; i++)
    Shellinsert(a[i]);
}
int main()
{
    int N,i;
    cin >> N;
    for(int j=0;j<N;j++)
    {
        cin>>i;
        Data.push_back(i);
    }
    ShellSort();
    vector<int>::iterator it;
    for(it = Data.begin();it != Data.end()-1;it++)
        cout << *it << ' ';
    cout << *it;
}

8b4550b15ab74bde421c6b3878eca1e7.png

方法四:借助STL建堆进行堆排序

STL关于堆的函数为

make_heap(iterator begin,iterator end, cmp)建堆

cmp=less()建大顶堆

cmp=greater()建小顶堆

pop_heap(iterator begin,iterator end, cmp)将堆第一个元素放到最后(取出第一个元素)然后重新按堆排列,注意,如果反复使用这个语句,只能取出两个值,必须要再加上pop_back()才能“真正”取出。

push_heap(iterator begin,iterator end, cmp)按照堆规则添加元素

使用堆排序的方法,将通过的时间降低到了两位数

比前三个算法又更快了许多。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


vector<int> Data;


void HeapSort()
{
  vector<int> Data2;
  Data2 = Data; 
  make_heap(Data2.begin(),Data2.end(),greater<int>());//借助STL建堆
  for(int i=0;i<Data.size();i++)
  {
    Data[i]=Data2[0];//取堆顶
    pop_heap(Data2.begin(),Data2.end(),greater<int>());
    Data2.pop_back();//取出并重排
  }
  return;
}


int main()
{
    int N,i;
    cin >> N;
    for(int j=0;j<N;j++)
    {
        cin>>i;
        Data.push_back(i);
    }
    HeapSort();
    vector<int>::iterator it;
    for(it = Data.begin();it != Data.end()-1;it++)
        cout << *it << ' ';
    cout << *it;
}

03b29f15d051202b768108d37224b229.png

总结:

以上三个算法,在实际运行时间上,逐个从四位数降到三位数再降到两位数,当然,两位数与STL的使用是有着密切的关系的,倘若我自己写堆函数,可能也无法达到两位数的惊人成绩,所以,STL在提升速度方面和简化代码方面有着巨大的作用,通过这一道题,实现了昨天推送中学习的几种重要算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值