如何删除C++循环列表中找到的最高元素旁边的元素

Posted

技术标签:

【中文标题】如何删除C++循环列表中找到的最高元素旁边的元素【英文标题】:How to delete element next to the highest found element in the circular list in 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;

   
 

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

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

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

【问题讨论】:

【参考方案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;
    

    如果maxi指向的节点具有最大值,则要删除的节点是maxi-&gt;next(而不是调用tmp2,我们将它称为node_to_delete)。 在删除node_to_delete之前,需要将节点maxinode_to_delete之后的节点连接起来(而不是调用tmp3,我们将其称为node_after_delete)。 如果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() 函数中的逻辑错误是:

    节点 maxi 和节点 node_after_delete (tmp3) 之间的连接不良 ==> maxi-&gt;next=tmp3; 而不是 tmp2-&gt;next=tmp3-&gt;next;, 节点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() 函数,但不确定它是否与您的匹配!!! 我编辑了评论,我认为插入功能正常工作,删除功能几乎正常工作,除了最高元素是列表中“最后一个”的这种情况,但我没有'不知道如何解决它,因为它应该被圈出列表......如果最后一个元素是最高的,第一个应该被删除,但它在我的代码中不起作用 我已经添加了案例的解决方案'最高元素是列表中的“最后一个”'

以上是关于如何删除C++循环列表中找到的最高元素旁边的元素的主要内容,如果未能解决你的问题,请参考以下文章

在没有循环的 C++ 中移动数组元素

如何在 C++ 中删除列表中的某些元素

如何在 Python 的 for 循环中删除列表元素? [复制]

如何在c ++中删除嵌套列表中的重复元素

python中如何用for循环输出一个列表

c++怎么删除array里面的某个元素?