Как я могу назначить указатель "this" как "temp"? - PullRequest
0 голосов
/ 04 мая 2020

Я вызываю функцию interleave, которая выглядит как

void AddressLinkedList::interleave(AddressLinkedList& other) {
    AddressLinkedList temp;
    AddressListNode* thisCur = this->head;
    AddressListNode* otherCur = other.head;
    for (int i = 0; i < this->length + other.length; i++) {
        if (i % 2 == 0) {
            temp.insertEnd(thisCur->data);
            thisCur = thisCur->next;
        }
        else if (i % 2 != 0) {
            temp.insertEnd(otherCur->data);
            otherCur = otherCur->next;
        }
    }
    return;
}

Эта функция должна переплетать односвязный список A со односвязным списком B вдоль линий, если A выглядело как "1, 2, 3 "и B выглядели как" 4, 5, 6 ", тогда при вызове linkedListA.interleave(linkedListB) должно получиться A" 1, 4, 2, 5, 3, 6 ". Мне успешно удалось создать такой список, проблема в том, что это список temp, но я не знаю, как его создать, чтобы это был указатель this с конечной целью linkedListA быть вышеупомянутым «односвязным списком А». Если это имеет значение, ниже приведен перегруженный оператор присваивания и функция insertEnd.

void AddressLinkedList::insertEnd(const Address& value) {
    if (length == 0) {
        this->insertStart(value);
        return;
    }
    AddressListNode* temp = new AddressListNode(value);
    length++;
    tail->next = temp;
    tail = temp;
}
AddressLinkedList& AddressLinkedList::operator=(const AddressLinkedList& other) {
    delete this;
    AddressListNode* current;
    current = other.head;
    while (current != nullptr) {
        insertEnd(current->data);
        current = current->next;
    }
    return *this;
}

1 Ответ

1 голос
/ 04 мая 2020

Поскольку interleave определяется как функция-член AddressLinkedList, она должна модифицировать (и работать над) объект, к которому она была вызвана. Таким образом, вам не нужно (и не нужно) создавать временный список, чтобы использовать его для построения вашей результирующей коллекции, а затем «назначить» его как this. Это возможно с некоторыми хитростями new, delete и raw pointer, но я бы не рекомендовал это (идея состояла бы в том, чтобы создать AddressListNode* как голову, а затем назначить эту новую голову там, где была оригинальная, но вам также пришлось бы удалить предыдущую цепочку AddressListNode * из оригинальной заголовка, чтобы избежать утечек памяти, как я уже сказал, не рекомендуется).

Предполагая, что ваш код, вызывающий этот метод, выглядит следующим образом:

AddressLinkedList A;
AddressLinkedList B;
... //inserting values to A and B
A.interleave(B);

Ваша реализация interleave должна выглядеть примерно так (это скорее доказательство концепции, чем рабочее решение, я ее не скомпилировал):

void AddressLinkedList::interleave(AddressLinkedList& other) {
    AddressListNode* thisCur = head;
    AddressListNode* otherCur = other.head;
    while (thisCur != nullptr) { //assumig that last node points to nullptr
        AddressListNode* nextNode = thisCur->next;
        AddressListNode* otherNext = otherCur->next;
        thisCur->next = otherCur; //attach it to node from other
        thisCur = thisCur->next; //advance to next node
        thisCur = nextNode; //reattach node that was originally after current
        thisCur = thisCur->next; //advance again to next node
        otherCur = otherNext ; //advance on other
    }
    other->head = nullptr; //loop above hijack nodes from other
}

Весь этот код делает, он занимает головы обеих ваших коллекций, перебирает this и для каждого узла присоединяет соответствующий узел из other. Фактически он изменит ваш объект, для которого вы первоначально вызвали метод interleave. Однако из-за изменения указателя AddressListNode он также уничтожит ваш исходный AddressLinkedList, который вы передали как и аргумент interleave. Поэтому вам, вероятно, следует изменить его так, чтобы для thisCur->next = otherCur; фактически создавалась копия Address и создавался новый узел.

...