插入排序:我做错了什么?
Insertion Sort: What am I doing Wrong?
我正在尝试进行插入排序。这首歌是一个简单的结构,包含艺术家和标题 属性。如果第一首歌曲的歌名在第二首歌曲的歌名之前,我将 CompareTitle(Song& s1, Song& s2) 称为 returns true。当代码的交换部分被注释掉时,排序条件似乎工作正常。如果没有,我会收到此错误。我不确定如何处理它:
playlist.cc:192:22: error: object of type 'Song' cannot be assigned because its copy assignment operator is implicitly deleted
*itr = j;
//do insertion sort
for(auto itr = newSongList.begin(); itr != newSongList.end(); ++itr)
{
for(auto jtr=itr; jtr != newSongList.begin(); --jtr){
cout << itr->GetTitle() << " " << jtr->GetTitle() << endl;
// if s1 is not before s2 then swap them
if(!Song::CompareTitle(*itr, *jtr)){
cout << "Swap True (" << itr->GetTitle() << "," << jtr->GetTitle() << " )"<< endl;
Song i = Song(itr->GetTitle(),itr->GetArtist());
Song j = Song(jtr->GetTitle(), jtr->GetArtist());
*itr = j;
*jtr = i;
cout << "Swap After (" << jtr->GetTitle() << "," << itr->GetTitle() << endl;
}
}
}
以下是歌曲和播放列表的结构:
#ifndef PLAYLIST_H
#define PLAYLIST_H
#include <functional> // For std::function
#include <string>
#include <list>
using namespace std;
extern void SongCallback();
class Song {
public:
explicit Song(const string& title, const string& artist,
const function<void()> = &SongCallback);
const string& GetTitle() const;
const string& GetArtist() const;
bool operator==(const Song& s) const;
bool operator()(const Song& s) const;
static bool CompareTitle(const Song& s1, const Song& s2);
static bool CompareArtistTitle(const Song& s1, const Song& s2);
private:
const string title_;
const string artist_;
const function<void()> callback_;
};
class Playlist {
public:
explicit Playlist() {}
void AddSong(const string& title, const string& artist);
unsigned int RemoveSongs(const string& title, const string& artist);
list<Song> PlaylistSortedByTitle() const;
list<Song> PlaylistSortedByArtistTitle() const;
unsigned int NumSongs() const;
unsigned int NumSongs(const string& artist) const;
private:
list<Song> songs_;
};
#endif // PLAYLIST_H
似乎每次您应该交换两个元素的迭代器时,您实际上是在 itr
和 jtr
之前将元素添加到容器中。
for(auto itr = newSongList.begin(); itr != newSongList.end(); ++itr)
{
for(auto jtr=itr; jtr != newSongList.begin(); --jtr){
cout << itr->GetTitle() << " " << jtr->GetTitle() << endl;
// if s1 is not before s2 then swap them
if(!Song::CompareTitle(*itr, *jtr)){
swap(*itr, *jtr);
}
}
}
在这里您可以使用 std::swap
作为交换功能,或者编写您自己的函数来切换歌曲的标题和艺术家,以及可能添加到其中的任何其他成员。 std::iter_swap
也可以作为替代。
因为你有 const title_
和 artist_
参数,你不能使用 assignment operator
.
编译器也不会生成assignment operator
。由于 assignment operator
的目的是在构造后更改成员,因此当其中一个成员永远无法更改时生成隐式 assignment operator
是没有意义的。编译器拒绝尝试猜测你想要它做什么,并强迫你提供你自己的 assignment operator
和你想要的语义。
我认为,相反,您可以使用 list::insert and list::erase 方法操作列表条目,如下所示,以获得您想要的结果。
for(auto itr = newSongList.begin(); itr != newSongList.end(); ++itr)
{
for(auto jtr=itr; jtr != newSongList.begin(); --jtr){
cout << itr->GetTitle() << " " << jtr->GetTitle() << endl;
// if s1 is not before s2 then swap them
if(!Song::CompareTitle(*itr, *jtr)){
cout << "Swap True (" << itr->GetTitle() << "," << jtr->GetTitle() << " )"<< endl;
Song i = Song(itr->GetTitle(),itr->GetArtist());
Song j = Song(jtr->GetTitle(), jtr->GetArtist());
newSongList.insert(itr, j); // extend list by inserting j song before itr song
newSongList.erase(itr); // itr is still pointing to original song
newSongList.insert(jtr, i); // extend list by inserting i song before jtr song
newSongList.erase(jtr); // jtr is still pointing to original song
cout << "Swap After (" << jtr->GetTitle() << "," << itr->GetTitle() << endl;
}
}
}
我正在尝试进行插入排序。这首歌是一个简单的结构,包含艺术家和标题 属性。如果第一首歌曲的歌名在第二首歌曲的歌名之前,我将 CompareTitle(Song& s1, Song& s2) 称为 returns true。当代码的交换部分被注释掉时,排序条件似乎工作正常。如果没有,我会收到此错误。我不确定如何处理它:
playlist.cc:192:22: error: object of type 'Song' cannot be assigned because its copy assignment operator is implicitly deleted *itr = j;
//do insertion sort
for(auto itr = newSongList.begin(); itr != newSongList.end(); ++itr)
{
for(auto jtr=itr; jtr != newSongList.begin(); --jtr){
cout << itr->GetTitle() << " " << jtr->GetTitle() << endl;
// if s1 is not before s2 then swap them
if(!Song::CompareTitle(*itr, *jtr)){
cout << "Swap True (" << itr->GetTitle() << "," << jtr->GetTitle() << " )"<< endl;
Song i = Song(itr->GetTitle(),itr->GetArtist());
Song j = Song(jtr->GetTitle(), jtr->GetArtist());
*itr = j;
*jtr = i;
cout << "Swap After (" << jtr->GetTitle() << "," << itr->GetTitle() << endl;
}
}
}
以下是歌曲和播放列表的结构:
#ifndef PLAYLIST_H
#define PLAYLIST_H
#include <functional> // For std::function
#include <string>
#include <list>
using namespace std;
extern void SongCallback();
class Song {
public:
explicit Song(const string& title, const string& artist,
const function<void()> = &SongCallback);
const string& GetTitle() const;
const string& GetArtist() const;
bool operator==(const Song& s) const;
bool operator()(const Song& s) const;
static bool CompareTitle(const Song& s1, const Song& s2);
static bool CompareArtistTitle(const Song& s1, const Song& s2);
private:
const string title_;
const string artist_;
const function<void()> callback_;
};
class Playlist {
public:
explicit Playlist() {}
void AddSong(const string& title, const string& artist);
unsigned int RemoveSongs(const string& title, const string& artist);
list<Song> PlaylistSortedByTitle() const;
list<Song> PlaylistSortedByArtistTitle() const;
unsigned int NumSongs() const;
unsigned int NumSongs(const string& artist) const;
private:
list<Song> songs_;
};
#endif // PLAYLIST_H
似乎每次您应该交换两个元素的迭代器时,您实际上是在 itr
和 jtr
之前将元素添加到容器中。
for(auto itr = newSongList.begin(); itr != newSongList.end(); ++itr)
{
for(auto jtr=itr; jtr != newSongList.begin(); --jtr){
cout << itr->GetTitle() << " " << jtr->GetTitle() << endl;
// if s1 is not before s2 then swap them
if(!Song::CompareTitle(*itr, *jtr)){
swap(*itr, *jtr);
}
}
}
在这里您可以使用 std::swap
作为交换功能,或者编写您自己的函数来切换歌曲的标题和艺术家,以及可能添加到其中的任何其他成员。 std::iter_swap
也可以作为替代。
因为你有 const title_
和 artist_
参数,你不能使用 assignment operator
.
编译器也不会生成assignment operator
。由于 assignment operator
的目的是在构造后更改成员,因此当其中一个成员永远无法更改时生成隐式 assignment operator
是没有意义的。编译器拒绝尝试猜测你想要它做什么,并强迫你提供你自己的 assignment operator
和你想要的语义。
我认为,相反,您可以使用 list::insert and list::erase 方法操作列表条目,如下所示,以获得您想要的结果。
for(auto itr = newSongList.begin(); itr != newSongList.end(); ++itr)
{
for(auto jtr=itr; jtr != newSongList.begin(); --jtr){
cout << itr->GetTitle() << " " << jtr->GetTitle() << endl;
// if s1 is not before s2 then swap them
if(!Song::CompareTitle(*itr, *jtr)){
cout << "Swap True (" << itr->GetTitle() << "," << jtr->GetTitle() << " )"<< endl;
Song i = Song(itr->GetTitle(),itr->GetArtist());
Song j = Song(jtr->GetTitle(), jtr->GetArtist());
newSongList.insert(itr, j); // extend list by inserting j song before itr song
newSongList.erase(itr); // itr is still pointing to original song
newSongList.insert(jtr, i); // extend list by inserting i song before jtr song
newSongList.erase(jtr); // jtr is still pointing to original song
cout << "Swap After (" << jtr->GetTitle() << "," << itr->GetTitle() << endl;
}
}
}