📣 独立日限时特惠: VIP通行证立减$68
查看: 1562| 回复: 1
跳转到指定楼层
上一主题 下一主题
收起左侧

删除链表节点时调用析构函数 一直报错"SIGABRT" 求问版上C++大神!

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
本帖最后由 2011051305 于 2017-8-15 03:55 编辑

我在做lintcode Remove all elements from a linked list of integers that have value val 这道题。Given 1->2->3->3->4->5->3, val = 3, you should return the list as 1->2->4->5。 题很简单,算法本身实现起来没什么问题。
我的问题是调用这个删除函数之后 不是linkedlist本身还有调用自己的析构函数么, 这时候就一直报错了。

代码的构成:
代码分三部分:
首先是Listnode的类和LLinkedlist的类(就是怎么通过ListNode建Linkedlist 打印Linkedlist这些);
接下来是lintcode这道题要求我们实现的函数,[size=14.6667px]ListNode * removeElements(ListNode * head, int val), 包裹在Solution类里, 也没问题,这个函数在lintcode可以AC。
接下来就是main drive,这里我首先建了linkedlist, 然后调用removeElements,然后打印新的链表。到这里都没问题。然后main函数准备结束,调用linkedlist的析构函数,在第26行出现报错。
不想当伸手党的,用Clion一步步设断点追到这个[size=14.6667px]问题,真的不知道怎么解决了:

我的测试数据 : 很简单 链表是7->null 然后要删除的val就是7 返回应该是个空链表即null.

我的报错:
[size=14.6667px]报错截图如下:
[size=14.6667px]代码如下 (在ubuntu paste里格式更容易看 [size=14.6667px]https://paste.ubuntu.com/25314115/[size=14.6667px] ) 谢谢各位C++大大! Bow!
[size=14.6667px]
  1. #include <iostream>
  2. using namespace std;

  3. class ListNode{
  4. public:
  5.     int val;
  6.     ListNode * next;
  7.     ListNode(int val){
  8.         this->val = val;
  9.         this->next = NULL;
  10.     }
  11. };
  12. class LinkedList{
  13. private:
  14.     ListNode * head;
  15. public:
  16.     LinkedList(){
  17.         head = NULL;
  18.     }
  19.     ~ LinkedList(){
  20.         ListNode * curr_node = head;
  21.         while (curr_node != NULL){
  22.             ListNode * delete_node = curr_node;
  23.             curr_node = curr_node->next;
  24.             delete_node->next = NULL; //断开delete_node
  25.             delete delete_node;
  26.         }
  27.     }
  28.     void insert(ListNode * node, int index){
  29.         if (head == NULL){
  30.             if (index != 0){
  31.                 return;
  32.             }
  33.             head = node;
  34.             return;
  35.         }
  36.         if (index == 0){
  37.             node->next = head;
  38.             head = node;
  39.             return;
  40.         }
  41.         ListNode * current_node = head;
  42.         int count = 0;

  43.         while (current_node->next != NULL && count < index-1){
  44.             current_node = current_node->next;
  45.             count += 1;
  46.         }
  47.         if (count == index - 1){
  48.             node->next = current_node->next;
  49.             current_node->next = node;
  50.         }
  51.     }
  52.     void output(ListNode * head){
  53.         if (head == NULL){
  54.             return;
  55.         }
  56.         if (head->next == NULL){
  57.             cout << head->val << "->NULL";
  58.             cout << endl;
  59.             return;
  60.         }
  61.         ListNode * curr_node = head;
  62.         while (curr_node->next != NULL){
  63.             cout << curr_node->val << "->";
  64.             curr_node = curr_node->next;
  65.         }
  66.         cout << curr_node->val << "->NULL";
  67.         cout << endl;

  68.     }
  69. };

  70. class Solution {
  71. public:
  72.     ListNode * removeElements(ListNode * head, int val) {
  73.         if (head == nullptr){
  74.             return head;
  75.         }
  76.         ListNode dummy(-1);  dummy.next = head;
  77.         ListNode * curr = &dummy;
  78.         while (curr->next){
  79.             if (curr->next->val != val){
  80.                 curr = curr->next;
  81.             }
  82.             else{
  83.                 ListNode * temp = curr->next;
  84.                 curr->next = temp->next;
  85.                 temp->next = nullptr;
  86.                 delete temp;
  87.             }
  88.         }
  89.         return dummy.next;
  90.     }
  91. };

  92. int main(){

  93.     // create linkedlist;
  94.     LinkedList linkedList;

  95.     // record the head
  96.     ListNode * head = new ListNode(7);
  97.     linkedList.insert(head, 0);

  98.     linkedList.output(head);
  99.     cout << "*****************" << endl;

  100.     Solution sol;
  101.     ListNode * newHead = sol.removeElements(head, 7);

  102.     linkedList.output(newHead);

  103.     return 0;
  104. }
复制代码




Screen Shot 2017-08-14 at 3.41.09 PM.png (159.77 KB, 下载次数: 2)

Screen Shot 2017-08-14 at 3.41.09 PM.png

评分

参与人数 1大米 +3 收起 理由
fentoyal + 3 也给lz补点米

查看全部评分


上一篇:什么时候开始准备实习比较好?
下一篇:地里有木有研究JavaScript的啊?
推荐
fentoyal 2017-8-17 10:49:14 | 只看该作者
全局:
本帖最后由 fentoyal 于 2017-8-17 10:51 编辑

LZ太逗了,我那个帖子居然每个楼都加米了!!谢谢lz大米!不想当米饭桶,光吃不干,所以我帮lz看了下这问题。
这题问题有点复杂,我先描述下,你再看代码。
问题不是coding的问题,主要是lz对OOD的思想还没有领会。
lz的Solution 类对着lz的linkedlist类的head一阵猛改,可整个removeElement函数里根本没用到LinkedList这个类。那lz把人家head改的乱起八糟后,通知人家了吗?LinkedinList里那个head还指着原来的位置啊。
详细解释就是,你的行为本质是这样的:
LinkedList 的head ->[7] -> NULL
同时你在main函数里也有个局部变量head->[7]->null
然后你通过main函数的局部变量head把7删了,head->null,然后又把这个head赋给了newHead: newHead->null
但你过程中没碰LinkedList的head呀人家还指着head->[7已经delete,剩下一个undefined空间]->null
这时候这么一个严重corrupt的list要被扔进你的析构函数析构,肯定各种崩溃呀。

但我为啥说你这其实是OOD的问题呢,因为你要删除你的list上的一个节点,这个删除函数是改变list的结构的,这个删除函数理应定义在list上,而不是由第三方的class Solution来做。
如果你的removeElement是定义在list上,你根本不需要暴露listNode的细节,也不用暴露Head给外面,client也不需要知道head的存在的(当然这个跟你LintCode的题目要求已经不一样了,抛开lintcode,只从OOD角度来说),你的removeElement也好,insert也好,都是对着自己class的head操作,这样就不会出现你上面那个外人篡改自己的数据,而自己不知情的情况了。
下面是改后的代码。我主要是从正确使用OOD角度修改的,如果只是简单把你代码改的能过,不用这么大改动,但是那样的代码设计问题很大,将来保不定还会出别的怪bug。
  1. #include <iostream>
  2. using namespace std;

  3. class LinkedList{
  4. private:
  5.     class ListNode{ // LisNode本身也属于LinkedList的实现细节,没必要暴露给外面
  6.     public:
  7.         int val;
  8.         ListNode * next;
  9.         ListNode(int val){
  10.             this->val = val;
  11.             this->next = NULL;
  12.         }
  13.     } * head;
  14. public:
  15.     LinkedList(){
  16.         head = NULL;
  17.     }
  18.     ~ LinkedList(){
  19.         ListNode * curr_node = head;
  20.         while (curr_node != NULL){
  21.             ListNode * delete_node = curr_node;
  22.             curr_node = curr_node->next;
  23.             delete_node->next = NULL; //断开delete_node
  24.             delete delete_node;
  25.         }
  26.     }
  27.     void insert(int val, int index){ // 如果客户想插入7,传7就好了呀,ListNode的定义不应该暴露client。
  28.         ListNode * node = new ListNode(val); //你内部把7变成节点。
  29.         if (head == NULL){
  30.             if (index != 0){
  31.                 return;
  32.             }
  33.             head = node;
  34.             return;
  35.         }
  36.         if (index == 0){
  37.             node->next = head;
  38.             head = node;
  39.             return;
  40.         }
  41.         ListNode * current_node = head;
  42.         int count = 0;

  43.         while (current_node->next != NULL && count < index-1){
  44.             current_node = current_node->next;
  45.             count += 1;
  46.         }
  47.         if (count == index - 1){
  48.             node->next = current_node->next;
  49.             current_node->next = node;
  50.         }
  51.     }
  52.     void output(){ //体会OOD思想,output本身是在此LinkedList的一个操作,干嘛要传人一个node呢?操作就应该且必须是自己的node呀。
  53.                    //你好好体会下,car有 Ignite()这个function,你需要定义成 void Ingite(Car mycar) 吗?不用的,因为Ignite的正确调用方法是 mycar.Ignite().
  54.         if (head == NULL){
  55.             return;
  56.         }
  57.         if (head->next == NULL){
  58.             cout << head->val << "->NULL";
  59.             cout << endl;
  60.             return;
  61.         }
  62.         ListNode * curr_node = head;
  63.         while (curr_node->next != NULL){
  64.             cout << curr_node->val << "->";
  65.             curr_node = curr_node->next;
  66.         }
  67.         cout << curr_node->val << "->NULL";
  68.         cout << endl;
  69.     }
  70.     void removeElements(int val) { //同样道理,head不需要。
  71.         if (head == nullptr){
  72.             return;
  73.         }
  74.         ListNode dummy(-1);  dummy.next = head;
  75.         ListNode * curr = &dummy;
  76.         while (curr->next){
  77.             if (curr->next->val != val){
  78.                 curr = curr->next;
  79.             }
  80.             else{
  81.                 ListNode * temp = curr->next;
  82.                 curr->next = temp->next;
  83.                 temp->next = nullptr;
  84.                 delete temp;
  85.             }
  86.         }
  87.         head = dummy.next;
  88.     }
  89.     //Bonus: Just a cooler way to do output, now you can cout<<linkedList<<endl; see below.
  90.     friend ostream & operator<< (ostream & os, const LinkedList & ll)
  91.     {
  92.         auto head = ll.head;
  93.         if (head == NULL){
  94.             return os;
  95.         }
  96.         if (head->next == NULL){
  97.             os << head->val << "->NULL";
  98.             os << endl;
  99.             return os;
  100.         }
  101.         ListNode * curr_node = head;
  102.         while (curr_node->next != NULL){
  103.             os << curr_node->val << "->";
  104.             curr_node = curr_node->next;
  105.         }
  106.         os << curr_node->val << "->NULL";
  107.         os << endl;
  108.         return os;
  109.     }
  110. };
  111. //这个Solution 类都多余,我直接全删了。反正你lintcode提交也过了不是?
  112. int main(){
  113.     // create linkedlist;
  114.     LinkedList linkedList;
  115.     linkedList.insert(7, 0);
  116.     linkedList.insert(8, 0);
  117.     linkedList.insert(7, 0);
  118.     //linkedList.output();
  119.     cout<<linkedList<<endl;
  120.     cout << "*****************" << endl;
  121.     linkedList.removeElements(7);
  122.     //linkedList.output();
  123.     cout<<linkedList<<endl;
  124.     return 0;
  125. }
复制代码

评分

参与人数 1大米 +3 收起 理由
2011051305 + 3 谢谢F神! 我才发现我的帖子回复通知!您真.

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表