0

私はこの削除機能を持っています:

Node* deleteNode(Node *head, Node *node)
{
    if (head != 0)
    {
        if (head == node)
            head = head->next;
        else
            head->next = deleteNode(head->next, node);
    }
    return head;
}

しかし、より明確にするために(私のプログラムの残りの機能はクラスにあるため)、次のようにしたいと思います。

void List::deleteNode()
{
    //the code comes here
}

(単連リストの先頭から削除したいのですが、ライブラリは使いたくないです。)

4

2 に答える 2

0

私はあなたがこれについて間違った方向に進んでいると思います。最初にクラスがどのように見え、どのように感じられるかを考え、次にそこで何が起こっているかを考えるべきです。コード、特にリストのようなものを処理するコードをクラスに入れることを検討している場合、最初に、クラスがサポートする必要がある操作 (追加、消去、検索?、インデックス?) の精神的なリストを作成します。次に、クラスに持たせたいインターフェイスについて考え始めます。次に、コードをクラスに入れるのは通常、小さなステップです。これは、そのほとんどが前の 2 つのステップですでに決定されているためです。

あなたのコードを見ると、戻り値はnext再帰呼び出しの後に前の要素のポインターをリセットするためにのみ使用されていることがわかります。したがって、関数をリストのユーザー用と内部のみで使用する関数に分けることができます。これは重要なポイントです。これは、クラスのインターフェースが、クラスのユーザー用のものを外部 (「パブリック」) に表示するだけでよいことを意味するためです。内部で行うことは、独自のビジネスです。これにより、クラスのユーザーを邪魔することなく、これを再帰から反復 (より効率的) に変更できます。

さて、あなたの場合、クラスに入れたいリストがあります。アドレスで要素を指定するリストから要素を削除できます。これは要素を破壊しませんが、それを呼び出し元に任せます (生のポインターは常に所有権の質問をしますが、それは別の問題です)。リストを埋める方法やノードを割り当てる方法など、他のことはまだ不明です。これにより、消去操作で次のユースケースが得られます。

List l;
... // fill l
Node* n = ... // some node
l.erase(n);
delete n;

リスト型の場合、これは次のようになります。

struct List
{
    void erase(Node* n)
    {
        m_head = doErase(m_head, n);
    }
private:
    static Node* doErase(Node* head, Node* node)
    {
        ... // your function here
    }

    Node* m_head;
};

まだいくつか不足していることに注意してください。特に、クラスをコピー不可にしたい場合や、ノードが null の場合 (例: assert(n);in erase()) またはリストにない場合 ( throw invalid_argument("node not element of list");in do_erase()) にどうするかを決定する必要があります。ただし、これで開始できることを願っています。

于 2013-06-08T09:27:03.130 に答える