簡體   English   中英

刪除C++中的鏈表數組

[英]Deleting an array of linked list in c++

我創建了存儲桶來插入我的數據,除了刪除所有節點外,一切正常。 如果我使用delete[] container刪除我的容器,那么只會刪除我所有鏈表的第一個節點。 我認為我所做的是合乎邏輯的,但它不起作用。 你能告訴我為什么嗎?(​​只有函數的最后一個循環值得關注,其他代碼供參考。)

#include <iostream>
#include <cmath>
using namespace std;

struct bucket{
    int val;
    bucket* next;
};


int countDigit(int max){
    int digits = 0;
    while(max>0){
        max = max/10;
        digits++;
    }
    return digits;
}

int findMax(int* arr, int l, int r){
    int max = arr[l];
    for(int i = l+1; i<=r; i++){
        if(max<arr[i]){
            max = arr[i];
        }
    }
    return max;
}

void createBucket(int* arr, int l, int r){
    int max = findMax(arr, l, r);
    int digits = findDigit(max);
    int divide = pow(10, digits-1);
    int maxPos = max/divide;
    int pos;//position of elements in the container
    bucket* container = new bucket[maxPos+1];
    bucket* cursor;
    //copying elements to their respective buckets
    for(int i=l; i<=r; i++){

        pos = arr[i]/divide;

        if(container[pos].val == 0){
            container[pos].val = arr[i];
            container[pos].next = NULL;
        }
        else{
            bucket* node = new bucket;
            cursor = &container[pos];
            node->val = arr[i];
            while(cursor->next!=NULL){
                cursor = cursor->next;
            }
            cursor->next = node;
            node->next = NULL;
        }
    }
    //copying the elements from the buckets to their respective position
    int j = 0;
    for(int i = 0; i<maxPos+1; i++){
        cursor = &container[i]; 
        while(cursor!=NULL && cursor->val!=0){
            arr[j] = cursor->val;
            cursor = cursor->next;
            j++;
        }
    }
    //deleting all nodes
    bucket* tmp;
    for(int i= 0; i<maxPos+1; i++){
        cursor = &container[i];
        while(cursor!=NULL){
            tmp = cursor;
            cursor = cursor->next;
            delete tmp;
        }
    }
}

它給出如下錯誤:

double free or corruption (out)
Aborted (core dumped)

最大的問題是您實際上沒有鏈表。 您有一個節點結構,並且您正在嘗試將節點串在一起,但是您缺少一個實際的類來為您維護您的數據結構。

自然,當您嘗試刪除數組時,只會刪除每個索引的第一個節點。 您有零個代碼來處理刪除整個列表。

下面是一個鏈表類的簡短示例。 它缺少相當多的功能,但它足以展示一些好的實踐以及它是如何工作的。

#include <iostream>

class IntList {
 public:
  IntList() = default;
  ~IntList();                           // Rule of 5
  IntList(const IntList& other);        // Rule of 5
  IntList(IntList&& other) noexcept;    // Rule of 5
  IntList& operator=(IntList other);    // Rule of 5
  IntList& operator=(IntList&& other);  // Rule of 5
  void push_back(int value);
  void print() const;  // Only here for ease of demo

  friend void swap(IntList& lhs, IntList& rhs);

 private:
  struct Node {
    int m_key = 0;
    Node* m_next = nullptr;

    Node(int key) : m_key(key) {}
  };

  Node* m_head = nullptr;
  Node* m_tail = nullptr;
};

IntList::~IntList() {
  while (m_head) {
    Node* tmp = m_head;
    m_head = m_head->m_next;
    delete tmp;
  }

  m_head = nullptr;
  m_tail = nullptr;
}

IntList::IntList(const IntList& other) {
  if (other.m_head) {
    // Set up first node
    this->m_head = new Node(other.m_head->m_key);
    m_tail = m_head;
    Node* otherWalker = other.m_head->m_next;
    while (otherWalker) {  // Handles the rest of the nodes
      m_tail->m_next = new Node(otherWalker->m_key);
      m_tail = m_tail->m_next;
      otherWalker = otherWalker->m_next;
    }
  }
}

IntList::IntList(IntList&& other) noexcept : IntList() { swap(*this, other); }

IntList& IntList::operator=(IntList other) {
  swap(*this, other);

  return *this;
}

IntList& IntList::operator=(IntList&& other) {
  swap(*this, other);

  return *this;
}

void IntList::push_back(int value) {
  Node* tmp = new Node(value);
  if (!m_head) {
    m_head = tmp;
    m_tail = m_head;
    return;
  }

  m_tail->m_next = tmp;
  m_tail = tmp;

  return;
}

void IntList::print() const {
  Node* walker = m_head;

  if (!walker) {
    std::cout << "Empty List.\n";
  }

  while (walker) {
    std::cout << walker->m_key << (walker->m_next ? ' ' : '\n');
    walker = walker->m_next;
  }
}

void swap(IntList& lhs, IntList& rhs) {
  using std::swap;

  swap(lhs.m_head, rhs.m_head);
  swap(lhs.m_tail, lhs.m_tail);
}

int main() {
  IntList one;
  one.push_back(42);
  one.push_back(55);

  IntList two(one);

  IntList three;
  three.push_back(350);
  three.push_back(240);
  three.push_back(609);

  IntList four(three);
  four.push_back(666);


  // While I can appreciate learning, there's no reason for a dynamically 
  // allocated array. SO trope of use a vector instead applies here. NOTE: a 
  // vector would not have helped with your code, it just takes away your 
  // responsibility to delete the array later. You'd still leak memory.
  IntList* const container = new IntList[4];
  container[0] = one;
  container[1] = two;
  container[2] = three;
  container[3] = four;

  for (int i = 0; i < 4; ++i) {
    container[i].print();
  }

  delete[] container;
}

IntList是一個表示整數單鏈表的類。 數據成員m_headm_tail代表列表的開頭和結尾。 m_tail是可選的,但我發現如果你知道列表的結尾,它會讓生活更輕松。 當涉及到從中間擦除時,雙向鏈表也讓你的生活變得更輕松,而且它們並沒有那么難寫。

該列表由節點組成,其中一個節點指向下一個節點的位置。 你已經有了這個。

解決您的問題的關鍵函數是析構函數~IntList() 仔細檢查該函數。 注意它是如何在你的整個列表中移動的,刪除每個節點。 這就是你所缺少的。 那和實際的列表類來完成所有這些。

因為每個IntList對象都照顧自己的內存,所以我只需要刪除動態數組。 當數組自毀時,它會調用每個元素的析構函數。 這意味着在每個IntList元素在其自身之后清除之后,然后刪除數組內存。 沒有泄漏,也沒有雙重釋放。

有助於理解數據結構的最重要的事情就是將其繪制出來。

我提到的良好實踐是 5 函數規則(0/3/5 規則)和復制交換習語。 規則 5 是必要的,因為鏈表類正在管理動態資源。 main 函數充分利用了復制構造函數。 請注意,該數組包含列表的副本。 如果我不想要副本,則必須將數組聲明為雙指針並將指針數組分配給IntLists IntList將在主函數結束時自行清理。

復制交換習語只是讓生活更輕松並減少代碼重復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM