【问题标题】:How to delete element next to the highest found element in the circular list in C++如何删除C++循环列表中找到的最高元素旁边的元素
【发布时间】:2017-03-08 19:02:21
【问题描述】:

我遇到了一些函数/算法的问题,希望你们能帮助我。任务是编写一个函数,该函数将删除单链循环列表中最高元素(最大值)之后的元素。我一直在尝试画这个,所以这对我来说更有意义,但它看起来仍然像黑暗艺术,但我设法想出了这样的功能:

struct node
{
 node * next;
 double data;
};

 void Insert_node(node * & head, double v)
 {
  node * p = new node;

  p->data = v;
  if(head)
  {
   p->next = head->next;
   head->next = p;
  }
  else p->next = p;
  head = p;
  }


void Delete_After_Max(node* & head)
{
   node * tmp=head;
   int counter=0,index=0;
   double maximum=0;

 if(tmp) // checking if the list is not empty
 {
    do
    {
      if(tmp->data>maximum)
      {
          maximum=tmp->data;
          index=counter+1;
      }
    counter++;
    tmp=tmp->next;
  } while(tmp!=head);
}

cout<<"Biggest value on the list: "<<maximum<<endl;
cout<<"licznik:"<<counter<<"  "<<"indeks: "<<index<<endl;

if(counter==(index+1))
   index=0;    //if last element is the maximum, first one will be deleted
 else
   index++; // incrementing to get index of the next element after maximum

node *tmp2=NULL;
//checking if the highest element was last(then we delete first one)
if(index==0)
    {
    index=counter;
    }
// checking if the highest element was somewhere else

node *tmp3=NULL;

int position=0;

if((index>0)&& (index<=counter))
   {
       tmp2=head;

       while(position<index-1)
        {
            tmp2=tmp2->next;
            position++;
        }

    tmp3=tmp2->next;
    tmp2->next=tmp3->next;

    if(head==tmp3)
    {
        head=head->next;
    }
    delete tmp3;

   }
 }

你觉得这个算法对吗?我不确定我的想法是否正确,所以代码可能完全错误:/

首先,我计算列表中的所有元素,找到最高的那个和它的索引,然后我可以使用它通过增加索引来删除之后的元素,对吗?我认为现在还可以,但是在那之后对我来说变得更难了,如果最大值是最后一个元素,我必须删除第一个元素,然后将最后一个元素与第二个元素“连接”?但是我不知道循环列表是否可以,所以请有人给我一个提示我做错了什么吗? ;)

我再次检查了它,它可以编译但它不能正常工作,我仍然不知道为什么,以及如何去做。我找不到任何可以基于的类似问题,任何形式的帮助都将不胜感激,我是新手,这就是为什么有这么多错误...

【问题讨论】:

    标签: c++ algorithm list linked-list circular-list


    【解决方案1】:

    在所提出的算法中,小错误会导致错误的结果。

    错误 1 - 最大的,在最后一个 while 循环中,tmp2 未初始化。

    初始化tmp2 = head 而不是tmp3 = head;

    tmp2 = head; // initialize tmp2
    while (position<index - 1)
    {
        tmp2 = tmp2->next;
        position++;
    }
    tmp3 = tmp2->next;
    

    错误 2 - 以 position 开头等于 1 会过早停止循环。

    使用第一个 position = 1 和 while 条件 (position < index - 1) 将循环减少 2 步。

    int position = 0;
    

    拼写错误 - 在if (index == 0) 条件下,缺少半列。

    行代码head = head-&gt;next 不以; 结尾。

    if (index == 0) 条件下,要么使用return 退出函数,要么通过在else { ... } 条件中插入最后一部分来防止执行意外操作。

    if (index == 0)
    {
        tmp2 = head;
        head = head->next;
        delete tmp2;
        // EXIT by return
    }
    

    增加了 N°1>>>>

    错误 3 - if (index == 0) 的情况是不可能的

    尝试删除循环链表的第一个节点 最大值放在最后一个节点是不可能的。

    • index = 0; 仅当if (counter == index) 时才可能。但在执行过程中,在将最大值的位置存储在 index = counter; 之后,counter 会增加 counter++;

    修改如下:

    if (counter == (index+1)) // detecting the last position
        index = 0;    //if last element is the maximum, first one will be deleted
    else
        index++; // incrementing to get index of the next element after maximum
    
    • 但是要删除第一个节点,if (index == 0) 的建议算法不起作用,因为需要存储前一个节点。

    解决方案 - 最好的解决方案是通过执行以下更改来强制最后一个 while 循环再继续执行一步:

    if (index == 0)
    {
        index = counter;
    }
    

    然后在(index == counter) with 时允许while循环:

    if ((index>0) && (index<=counter)) // allow for the last
    {
        tmp2 = head;
        while (position<index - 1)
    

    并且在删除tmp3节点之前,修改headtmp3 == head

        tmp3 = tmp2->next;
        tmp2->next = tmp3->next;
        if (head==tmp3) { // when the node to delete is the head
            head = head->next; // shift head to the next node
        }
        delete tmp3;
    

    新增第 2 个>>>>

    输出 - 这是使用建议的值列表时获得的结果。

    第一个元素6是被删除的(最后一个元素的下一个元素 18 在循环链表中)。

    [ 6, 9, 13, 12, 1, 10, 15, 4, 6, 18, ].
    Biggest value on the list: 18
    [ 9, 13, 12, 1, 10, 15, 4, 6, 18, ].
    

    新增第3号>>>>

    这里是函数Delete_After_Max()的完整源代码:

    void Delete_After_Max(node* & head)
    {
        node * tmp = head;
        int counter = 0, index = 0;
        double maximum = -1;
    
        if (tmp) // checking if the list is not empty
        {
            do
            {
                if (tmp->data>maximum)
                {
                    maximum = tmp->data;
                    index = counter;
                }
                counter++;
                tmp = tmp->next;
            } while (tmp != head);
        }
    
        std::cout << "Biggest value on the list: " << maximum << "\n";
        if (counter == (index+1))
            index = 0;    //if last element is the maximum, first one will be deleted
        else
            index++; // incrementing to get index of the next element after maximum
    
        node *tmp2 = NULL;
        //checking if the highest element was last(then we delete first one)
        if (index == 0)
        {
            tmp2 = head;
            std::cout << tmp2->data << ", ";
            index = counter;
            //head = head->next;
            //delete tmp2;
            // EXIT
        }
        // checking if the highest element was somewhere else
    
        node *tmp3 = NULL;
    
        int position = 0; // ERROR 1;
    
        // if ((index>0) && (index<counter))
        if ((index>0) && (index<=counter))
        {
            // ERROR tmp3 = head;
            tmp2 = head;
            while (position<index - 1)
            {
                tmp2 = tmp2->next;
                position++;
            }
            tmp3 = tmp2->next;
            tmp2->next = tmp3->next;
            if (head==tmp3) {
                head = head->next;
            }
            delete tmp3;
        }
    }
    

    增加了 N°4>>>>

    在更新函数Delete_After_Max()下方显示的逻辑删除最大值以下的节点是错误的。

    bool Delete_After_Max(node* & head)
    {
        node *maxi=Find_Maximum(head);
        std::cout << "Biggest value on the list: " << maxi->data << "\n";
    
        if(!Is_Empty) // !Is_Empty because this function is not working properly so i had to negate it until i find out why ;)
        {
            cout<<"the list is empty";
            return false;
        }
        else
        {
            node *tmp3=NULL;
            node *tmp2=maxi->next;
            tmp3=tmp2->next;
            tmp2->next=tmp3->next;
            if (head==tmp3) {
                head = head->next;
            }
            delete tmp3;
    
            cout<<"one element deleted";
    
            return true;
        }
    }
    
    1. 如果maxi指向的节点具有最大值,则要删除的节点是maxi-&gt;next(而不是调用tmp2,我们将它称为node_to_delete)。
    2. 在删除node_to_delete之前,需要将节点maxinode_to_delete之后的节点连接起来(而不是调用tmp3,我们将其称为node_after_delete)。
    3. 如果node_to_deletehead,则需要在删除前将head 更新为下一个节点。

    那么,函数中新的删除部分就变成了:

    // Step 1
    node *node_to_delete = maxi->next;
    // Step 2
    node *node_after_delete = node_to_delete->next;
    maxi->next = node_after_delete;
    // Step 3
    if (node_to_delete == head) {
        head = head->next;
    }
    delete node_to_delete;
    

    所以,Delete_After_Max() 函数中的逻辑错误是:

    1. 节点 maxi 和节点 node_after_delete (tmp3) 之间的连接不良 ==> maxi-&gt;next=tmp3; 而不是 tmp2-&gt;next=tmp3-&gt;next;
    2. 节点node_to_delete (tmp2) ==> 的错误定义if (head==tmp2)delete tmp2; 而不是if (head==tmp3)delete tmp3;

    【讨论】:

    • 好的,我修复了您指出的错误,但是当我尝试运行整个代码时,它会崩溃..但是代码的其他部分可能存在问题,但是现在我只需要这个算法是正确的;)。所以现在我修复了错误,算法假设可以正常工作?或者我错过了一些案例,但仍然没有任何意义?
    • 我处理了代码,但是将位置设置为 1,而不是像你说的那样设置为 0,并且它正在工作:元素数量减少 1,并且在我之后不显示最大元素之后的元素使用这个函数,但是有一个问题——如果最大值在最后一个元素,它就会崩溃,我不知道如何解决这个问题
    • @WojtekMika,为了确保函数Delete_After_Max(),有必要知道如何在循环链表中添加/插入数据。您能否编辑问题并添加struct node 定义和insert() 函数? 注意:我创建了自己的简单insert() 函数,但不确定它是否与您的匹配!!!
    • 我编辑了评论,我认为插入功能正常工作,删除功能几乎正常工作,除了最高元素是列表中“最后一个”的这种情况,但我没有'不知道如何解决它,因为它应该被圈出列表......如果最后一个元素是最高的,第一个应该被删除,但它在我的代码中不起作用
    • 我已经添加了案例的解决方案'最高元素是列表中的“最后一个”'
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    相关资源
    最近更新 更多