Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;泛型插入排序_C++_Algorithm_Sorting_Generics - Fatal编程技术网

C++ C++;泛型插入排序

C++ C++;泛型插入排序,c++,algorithm,sorting,generics,C++,Algorithm,Sorting,Generics,我写这篇文章是为了更好地理解排序算法和泛型函数。我已经实现了一个基本的插入排序算法,我正在尝试使它能够处理多个数据结构(至少是列表和数组) 因为我可以访问如下列表:list[N]来获取值,所以我认为我需要使用迭代器。所以我试图转换我的解决方案。以下是我试图修改的基本插入排序算法: int *insertionsort(int *a) { for (int i = 1; i<length(a); ++i) { int k = a[i]; int j = i-1;

我写这篇文章是为了更好地理解排序算法和泛型函数。我已经实现了一个基本的插入排序算法,我正在尝试使它能够处理多个数据结构(至少是列表和数组)

因为我可以访问如下列表:list[N]来获取值,所以我认为我需要使用迭代器。所以我试图转换我的解决方案。以下是我试图修改的基本插入排序算法:

int *insertionsort(int *a)
{
  for (int i = 1; i<length(a); ++i)
  {
    int k = a[i];
    int j = i-1;
    {
      while (j>=0 && a[j] > k)
      { 
        a[j+1] = a[j--];
      }
    a[j+1] = k;
  }
  return a;
}
int*insertionsort(int*a)
{
对于(int i=1;i=0&&a[j]>k)
{ 
a[j+1]=a[j--];
}
a[j+1]=k;
}
返回a;
}
以下是到目前为止我对通用版本的了解:

template <class T>
T insertionsort(T a)
{
  for (auto i = a.begin()+1; i<a.end(); ++i)
  {
    auto k = i;
    auto j = i-1;
    while (j>=a.begin() && *j>*k)  
    {
      (j + 1) = j--; 
    }
    (j + 1) = k;
  }  
   return a;
} 
模板
T插入排序(T a)
{
对于(自动i=a.begin()+1;i=a.begin()&&&*j>*k)
{
(j+1)=j--;
}
(j+1)=k;
}  
返回a;
} 

不幸的是,我似乎根本无法让这个泛型函数正确排序。我已经看了很长一段时间没有运气了。想法?

我认为您对取消引用迭代器/指针感到困惑。这应该起作用:

template <class T>
T insertionsort(T a)
{
    if(a.begin() == a.end()) // return a when it's empty
        return a;
    for(auto i = a.begin() + 1; i < a.end(); ++i)
    {
        auto k = *i; // k is the value pointed by i
        auto j = i - 1;
        while(j >= a.begin() && *j > k)  
        {
            *(j + 1) = *j; // writen in 2 lines for clarity
            j--;
        }
        *(j + 1) = k;
    }  
    return a;
} 
模板
T插入排序(T a)
{
if(a.begin()==a.end())//当a为空时返回a
返回a;
对于(自动i=a.begin()+1;i=a.begin()&&*j>k)
{
*(j+1)=*j;//为了清晰起见,请写两行
j--;
}
*(j+1)=k;
}  
返回a;
} 

对于更通用的解决方案,最好传递要排序的范围,而不是要排序的对象,标准算法如:

模板
void insertionsort(双向迭代器begin,双向迭代器end)//注意迭代器
{//按值传递
if(begin==end)return;//如果范围为空,则中止
用于(自动i=begin+1;i*i)
{
*(j+1)=*j;
j-=!flag;//如果j==开始,则不递减(无分支)
}
*(j+1)=*i;
}  
}

该函数是一个过程,不返回任何内容,对原始范围进行排序。

仅发布供OP参考,不太可能长寿。如果您非常倾向于使用C++11,并且不喜欢键入,那么这可能会奏效

template<typename Iter>
void insertion_sort(Iter first, Iter last)
{
    for (Iter it = first; it != last; ++it)
        std::rotate(std::upper_bound(first, it, *it), it, std::next(it));
}
模板
无效插入排序(Iter优先,Iter最后)
{
for(Iter it=第一;it!=最后;++it)
std::rotate(std::上界(第一,it,*it),it,std::next(it));
}
所用功能的相关链接:


,及。享受。

你们有什么错误吗?斯特伦(a)怎么了?这根本不是得到整数数组长度的方法;您必须将长度与数组一起传递。
(j+1)=任何内容都没有意义。您的意思是取消对迭代器的引用吗?在下一页中,您将找到一个很好的示例,说明如何在C++11中实现插入排序:
length(a)
也没有意义。此外,在多个点上,您可以通过使用
j
j--
调用未定义的行为,而不使用正确的排序关系。这段代码充满了错误。我认为把
j
移过
a
的左端是不合适的。如果
a
为空,
a.begin()+1
也是UB。非常感谢,我曾经有过类似的解决方案,但在将其分配给auto k时没有取消对I的引用。此解决方案非常有效。@user2357112您是对的。我只是简单地修复了这里的解引用。如果A.begin()+1是UB,那么访问输入的第二个元素的最佳方式是什么?@UserAce如果
A.size()==0
,那么它已经被排序了,所以您可以简单地返回它。使用
a.begin()+1
将不再是问题。我认为您可以通过使用
std::next
(C++11)而不是
+1
I!=结束
j!=begin
(虽然我想需要进行特殊检查,因为在某些情况下,
begin-1
可能是UB)。@WhozCraig我现在正在解决这个问题:)感谢传入一系列数据,然后允许对数据的子集进行排序有什么好处?@DyP我在发布这篇文章之前正在考虑一个双向解决方案,但正如您所说,我已经注意到,
j>=begin
等价物可能是一个问题。对于双向迭代器,我只允许知道两个迭代器是否相同,但我们需要知道迭代器是否通过了
begin
(在
begin
之前)@UserAce yes。该算法更为通用:您不允许用户对某个对象的特定部分(例如容器)进行排序,而只是强制对整个对象进行排序。当我在@nosid的评论中看到这一点时,我认为“WTF,插入两行排序!”+1用于使用二进制搜索扫描已排序的子序列。
template<typename Iter>
void insertion_sort(Iter first, Iter last)
{
    for (Iter it = first; it != last; ++it)
        std::rotate(std::upper_bound(first, it, *it), it, std::next(it));
}