简体   繁体   English

插入排序:我在做什么错了?

[英]Insertion Sort: What am I doing Wrong?

I am trying to do an insertion sort. 我正在尝试进行插入排序。 The song is a simple structure containing an Artist and Title property. 这首歌是一个简单的结构,包含Artist和Title属性。 I call the CompareTitle(Song& s1, Song& s2) which returns true if the song title of the first song is before the second song's title. 我调用CompareTitle(Song&s1,Song&s2),如果第一首歌的歌曲标题在第二首歌的标题之前,则返回true。 The sort condition seems to work fine when the swapping portion of the code is commented out. 当代码的交换部分被注释掉时,排序条件似乎可以正常工作。 When not, I get this error. 否则,我会收到此错误。 Im not sure how to approach it: 我不确定如何处理:

playlist.cc:192:22: error: object of type 'Song' cannot be assigned because its copy assignment operator is implicitly deleted *itr = j; playlist.cc:192:22:错误:“歌曲”类型的对象无法分配,因为它的副本分配运算符被隐式删除* 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;
        }
    }
}

Below is the structure of the song and playlist: 以下是歌曲和播放列表的结构:

#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

It would seem that every time you should be swapping iterator the two elements, you are instead adding elements to the container before both itr and jtr . 似乎每次您都应该交换迭代器这两个元素时,您实际上是在itrjtr之前将元素添加到容器中。

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);
        }
    }
}

Here you can either use std::swap as the swap function, or write your own function to switch the titles and artists of the songs, along with any other members that may be added to them. 在这里,您可以将std::swap用作交换函数,或者编写自己的函数来切换歌曲的标题和艺术家以及可能添加到其中的任何其他成员。 std::iter_swap could also be used as an alternative. std::iter_swap也可以用作替代方法。

std::swap on CPP reference CPP参考上的std::swap

std::iter_swap on CPP reference CPP参考上的std::iter_swap

Since, you have const title_ and artist_ params, you can't assign and overwrite these using assignment operator . 由于您具有const title_artist_参数,因此无法使用assignment operator分配和覆盖它们。

The compiler will also not generate assignment operator . 编译器也不会生成assignment operator Since the purpose of an assignment operator is to alter members after construction, it doesn't make sense to generate an implicit assignment operator when one of the member can never be altered. 由于assignment operator的目的是在构造后更改成员,因此当永远无法更改成员之一时,生成隐式assignment operator是没有意义的。 The compiler refuses to try and guess what you want it to do and forces you to provide your own assignment operator with the semantics you want. 编译器拒绝尝试猜测您要执行的操作,并强迫您向自己的assignment operator提供所需的语义。

I think instead, what you can do is manipulate the list entries using list::insert and list::erase methods, like I've shown below to achieve your desired result. 我想相反,您可以做的是使用list :: insertlist :: 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;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM