【问题标题】:How to reverse a chain of linked memory in a linked list?如何反转链表中的链接内存链?
【发布时间】:2021-03-02 02:27:55
【问题描述】:

现在,我正在尝试为双向链表编写反向方法。这不仅是您从头到尾反转的方法之一,而是从一个点开始并在开始后的一个点结束的列表的一部分。该方法接受称为startPointendPointListNode 指针引用,它们应该指向链接内存中链的新起点和终点。序列开始之前的ListNodenext 成员(所以startPoint->prev)应该指向新的开始,而序列结束之后的ListNodeprev 成员(所以@987654330 @) 应该指向新的结束。

我应该指出的一个关键方面是我们可能分配任何新的ListNodes

在我的 List.h 文件中,我有一个私有类 ListNode。我将它与我的 List 类的其余部分一起提供:

template <class T>
class List {
  private:
    class ListNode {
      public:
        ListNode();
        ListNode(const T & ndata);
        ListNode* next;
        ListNode* prev;
        const T data;
    };

  public:
    List();
    List(const List<T>& other);
    List<T>& operator=(const List<T>& rhs);
    int size() const;
    void print(ostream& os = std::cout) const;
    bool empty() const;
    ~List();
    void insertFront(const T& ndata);
    void insertBack(const T& ndata);
    void reverse();
    void tripleRotate();
    List<T> split(int splitPoint);

  private:
    ListNode* head_;
    ListNode* tail_;
    int length_;
    void _copy(const List<T>& other);
    void _destroy();

    /**
     * Helper function to reverse a sequence of linked memory inside a
     * List, starting at startPoint and ending at endPoint. You are
     * responsible for updating startPoint and endPoint to point to the
     * new starting and ending points of the rearranged sequence of
     * linked memory in question.
     *
     * @param startPoint A pointer reference to the first node in the
     *  sequence to be reversed.
     * @param endPoint A pointer reference to the last node in the
     *  sequence to be reversed.
     */
    void reverse(ListNode*& startPoint, ListNode*& endPoint);
};

在我的 List.hpp 文件中,我有反向方法本身。我不知道如何准确地写它。这是我到目前为止所拥有的(显然不起作用):

template <typename T>
void List<T>::reverse(ListNode *& startPoint, ListNode *& endPoint) {
  if (startPoint == endPoint) {
    return;
  }
  //startPoint should point at the new start, endPoint should point at the new end.
  ListNode* current = startPoint;
  ListNode* before_start_point = startPoint->prev;
  ListNode* after_end_point = endPoint->next;
  while (current != after_end_point) {
    ListNode* temp = current->next;
    current->next = current->prev;
    current->prev = temp;
    if (temp == endPoint) {
      endPoint = startPoint;
      startPoint = current;
    }
    current = temp;
  }
}

List.hpp 文件的其余部分:

template <class T>
List<T>::List() { 
    head_ = NULL;
    tail_ = NULL;
    length_ = 0;
}

template <typename T>
void List<T>::_destroy() {
  ListNode* current = head_;
  while (current != NULL) {
    ListNode* temp = current->next;
    delete current;
    current = temp;
  }
}

template <typename T>
void List<T>::insertFront(T const & ndata) {
  ListNode* newNode = new ListNode(ndata);
  //Case where there the list is empty
  if (head_ == NULL) {
    head_ = newNode;
    tail_ = newNode;
    newNode->next = NULL;
    newNode->prev = NULL;
  }
  else {
    newNode->next = head_;
    newNode->prev = NULL;
    head_->prev = newNode;
    head_ = newNode;
  }
  length_++;
}

template <typename T>
void List<T>::insertBack(const T & ndata) {
  ListNode* newNode = new ListNode(ndata);
  if (tail_ == NULL) {
    head_ = newNode;
    tail_ = newNode;
    newNode->next = NULL;
    newNode->prev = NULL;
  }
  else {
    newNode->prev = tail_;
    newNode->next = NULL;
    tail_->next = newNode;
    tail_ = newNode;
  }
  length_++;
}

template <typename T>
typename List<T>::ListNode* List<T>::split(ListNode* start, int splitPoint) {
  //There will be splitPoint number of nodes remaining in the current list
  ListNode* curr = start;
  if (splitPoint == 0) {
    return curr;
  }

  //Takes you to the start of the new list
  for (int i = 0; i < splitPoint && curr != NULL; i++) {
    curr = curr->next;
  }

  if (curr != NULL) {
      curr->prev->next = NULL;
      curr->prev = NULL;
  }

  //Return the head of the new sublist
  return curr;
}

template <typename T>
void List<T>::tripleRotate() {
  if (length_ < 3) {
    return;
  }
  else {
    int third_element_counter = 1;
    bool first_rotation = true;
    int divisible_by_three = length_ % 3;
    ListNode* current = head_;
    while (current != NULL) {
      if (third_element_counter != 3) {
        third_element_counter++;
      }
      else {
        ListNode* first = current->prev->prev;
        ListNode* temp_first_prev = first->prev;
        ListNode* second = current->prev;
        ListNode* temp_current = current;
        ListNode* temp_current_next = current->next; 
        second->prev = temp_first_prev;
        if (temp_first_prev != NULL) {
          temp_first_prev->next = second;
        }
        if (temp_current_next != NULL) {
          temp_current_next->prev = first;
        }
        current->next = first;
        first->next = temp_current_next;
        first->prev = temp_current;
        if (first_rotation) {
          head_ = second;
          first_rotation = false;
        }
        if (divisible_by_three == 0) {
          tail_ = first;
        }
        current = first;
        third_element_counter = 1;
      }
      current = current->next;
    }
  }
}

template <typename T>
void List<T>::reverse() {
  reverse(head_, tail_);
}

感谢任何形式的帮助。

【问题讨论】:

  • 您没有提供足够的代码。 List 类是什么?
  • @MysteriousUser 刚刚编辑了我的帖子。您现在应该可以看到 List 类了。
  • @HughJass24 能否请您提供List 方法的实现?所以我们可以完全测试它而无需实现它们。
  • @MysteriousUser 刚刚添加了实现。我事先测试了所有其他功能,它们都可以工作。但是,反向功能不起作用。

标签: c++ linked-list doubly-linked-list


【解决方案1】:

根据您的代码,我手动创建了一个包含十个整数的列表:

    List<int> my_list;
    for(int i = 0; i < 10; i++) {
        my_list.insertBack(i);
    }

然后,我打印了列表:

std::cout << "Before reverse:" << std::endl;
    my_list.print();

输出是:

Before reverse:
Node: 0
Node: 1
Node: 2
Node: 3
Node: 4
Node: 5
Node: 6
Node: 7
Node: 8
Node: 9

然后,我运行了您的反向函数的略微修改版本:

template <typename T>
void List<T>::reverse(ListNode *& startPoint, ListNode *& endPoint) {
  if (startPoint == endPoint) {
    return;
  }

  //startPoint should point at the new start, endPoint should point at the new end.
  ListNode* current = startPoint;
  ListNode* before_start_point = startPoint->prev;
  ListNode* after_end_point = endPoint->next;
  while (current != after_end_point) {
    std::cout << "Working with current node " << current->data << std::endl;
    ListNode* temp = current->next;
    std::cout << "Temp is " << (temp ? temp->data : 0) << std::endl;
    current->next = current->prev;
    std::cout << current->data << "'s new next is now " << (current->next ? current->next->data : 0) << std::endl;
    current->prev = temp;
    std::cout << current->data << "'s new prev is now " << (current->prev ? current->prev->data : 0) << std::endl;

    if (temp == endPoint) {
      endPoint = startPoint;
      startPoint = temp;
    }
    current = temp;
  }
}

并再次打印:

    std::cout << "After reverse:" << std::endl;
    my_list.print();

输出是:

After reverse:
Node: 9
Node: 8
Node: 7
Node: 6
Node: 5
Node: 4
Node: 3
Node: 2
Node: 1
Node: 0

所以看来唯一的问题是在while 循环末尾的if 块中,您在其中分配startPoint = current 而它应该是startPoint = endPointstartPoint = temp(因为当if 为真,temp 等于 endPoint)。

这是完整的代码(也可以在https://godbolt.org/z/nad7vT 中找到):

#include <iostream>

template <class T>
class List {
  private:
    class ListNode {
      public:
        ListNode();
        ListNode(const T & ndata) : data{ndata} {};
        ListNode* next;
        ListNode* prev;
        const T data;
    };

  public:
    List();
    List(const List<T>& other);
    List<T>& operator=(const List<T>& rhs);
    int size() const;
    void print(std::ostream& os = std::cout) const;
    bool empty() const;
    ~List() {};
    void insertFront(const T& ndata);
    void insertBack(const T& ndata);
    void reverse();
    void reverseNth(int n);
    void tripleRotate();
    List<T> split(int splitPoint);

  private:
    ListNode* head_;
    ListNode* tail_;
    int length_;
    void _copy(const List<T>& other);
    void _destroy();

    /**
     * Helper function to reverse a sequence of linked memory inside a
     * List, starting at startPoint and ending at endPoint. You are
     * responsible for updating startPoint and endPoint to point to the
     * new starting and ending points of the rearranged sequence of
     * linked memory in question.
     *
     * @param startPoint A pointer reference to the first node in the
     *  sequence to be reversed.
     * @param endPoint A pointer reference to the last node in the
     *  sequence to be reversed.
     */
    void reverse(ListNode*& startPoint, ListNode*& endPoint);
};

template <typename T>
void List<T>::reverse(ListNode *& startPoint, ListNode *& endPoint) {
  if (startPoint == endPoint) {
    return;
  }

  //startPoint should point at the new start, endPoint should point at the new end.
  ListNode* current = startPoint;
  ListNode* before_start_point = startPoint->prev;
  ListNode* after_end_point = endPoint->next;
  while (current != after_end_point) {
    std::cout << "Working with current node " << current->data << std::endl;
    ListNode* temp = current->next;
    std::cout << "Temp is " << (temp ? temp->data : 0) << std::endl;
    current->next = current->prev;
    std::cout << current->data << "'s new next is now " << (current->next ? current->next->data : 0) << std::endl;
    current->prev = temp;
    std::cout << current->data << "'s new prev is now " << (current->prev ? current->prev->data : 0) << std::endl;

    if (temp == endPoint) {
      endPoint = startPoint;
      startPoint = temp;
    }
    current = temp;
  }
}

template <class T>
List<T>::List() { 
    head_ = NULL;
    tail_ = NULL;
    length_ = 0;
}

template <typename T>
void List<T>::_destroy() {
  ListNode* current = head_;
  while (current != NULL) {
    ListNode* temp = current->next;
    delete current;
    current = temp;
  }
}

template <typename T>
void List<T>::insertFront(T const & ndata) {
  ListNode* newNode = new ListNode(ndata);
  //Case where there the list is empty
  if (head_ == NULL) {
    head_ = newNode;
    tail_ = newNode;
    newNode->next = NULL;
    newNode->prev = NULL;
  }
  else {
    newNode->next = head_;
    newNode->prev = NULL;
    head_->prev = newNode;
    head_ = newNode;
  }
  length_++;
}

template <typename T>
void List<T>::insertBack(const T & ndata) {
  ListNode* newNode = new ListNode(ndata);
  if (tail_ == NULL) {
    head_ = newNode;
    tail_ = newNode;
    newNode->next = NULL;
    newNode->prev = NULL;
  }
  else {
    newNode->prev = tail_;
    newNode->next = NULL;
    tail_->next = newNode;
    tail_ = newNode;
  }
  length_++;
}

template <typename T>
void List<T>::print(std::ostream& os) const {
    for(const ListNode *it = head_; it != nullptr; it = it->next) {
        os << "Node: " << it->data << std::endl;
    }
}

template <typename T>
void List<T>::reverse() {
  reverse(head_, tail_);
}

int main() {

    List<int> my_list;
    for(int i = 0; i < 10; i++) {
        my_list.insertBack(i);
    }

    std::cout << "Before reverse:" << std::endl;
    my_list.print();
      
    my_list.reverse();

    std::cout << "After reverse:" << std::endl;
    my_list.print();

    
    return 0;
}

【讨论】:

    猜你喜欢
    • 2012-02-23
    • 2016-04-07
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多