【问题标题】:C++ Deleting from a List with a start position and a endC ++从具有开始位置和结束位置的列表中删除
【发布时间】:2020-04-26 08:41:56
【问题描述】:

如何从列表中删除,例如从位置 1 到 4?

我只是用列表中的 1 个元素解决了这个删除问题:

void delPos(int iPos) {
  ListElem *pElemToDelete = mpHead;
  for (int i = 0; i < iPos; ++i) {
    pElemToDelete = pElemToDelete->mpNext;
  }
  if (pElemToDelete != nullptr) {
    if (mpHead == pElemToDelete) {
      mpHead = pElemToDelete->mpNext;
      delete pElemToDelete;
    } else {
      for (ListElem *pTmp = mpHead; pTmp != nullptr; pTmp = pTmp->mpNext) {
        if (pTmp->mpNext == pElemToDelete) {
          pTmp->mpNext = pElemToDelete->mpNext;
          delete pElemToDelete;
          return;
        }
      }
    }
  }

对于位置删除(从头到尾)我得到了这个:

void deleteElem(int start, int end) {
  ListElem *pTmp1 = m_pHead;
  ListElem *pTmp2 = m_pHead;
  for (int i = 0; i < end; ++i) {
    if (i < start - 1) {
      if (pTmp1->m_pNext != nullptr) {
        pTmp1 = pTmp1->m_pNext;
      }
    }
    if (pTmp2->m_pNext != nullptr) {
      pTmp2 = pTmp2->m_pNext;
    }
  }
  if (start == 0) {
    m_pHead = pTmp2->m_pNext;
  } else {
    pTmp1->m_pNext = pTmp2->m_pNext;
  }
}

但它并没有真正被删除对吧?它只显示指向正确元素的下一个指针。我像上面一样用 1 个元素尝试它,但它不起作用。

也许你们可以给我一些建议?

【问题讨论】:

  • 您将其作为家庭作业/练习来实现,还是为了弄清楚如何实现列表,或者您真的需要一个您想要使用的列表?
  • 这不是很明显的解决方法,但是试着用普通的笔和纸画出你想要的东西,它会让你思考你的列表是如何连接的,以及你想要实现什么。跨度>
  • t.niese 它是我学习列表基础知识的练习。是的,我需要它作为列表@Artem Bondar是的,我做到了..我的问题是我来自java有一个垃圾收集器所以我只需要将指针的引用设置到正确的位置并删除未使用的元素一个列表..在c ++中你需要自己删除,它的过程不同..我想从位置1删除到4,其他的应该显示出来。
  • @MoFug -- 你知道如何删除整个列表吗?这应该与删除整个列表的步骤几乎相同。
  • @PaulMcKenzie 你的意思是这样的吗? ListElem* pTmp = mpHead; for(ListElem* pTmp = mpHead;pTmp != nullptr;pTmp = pTmp-&gt;mpNext) { delete pTmp;// return; }

标签: c++ linked-list singly-linked-list delete-operator


【解决方案1】:

对于初学者这个功能

void delPos(int iPos) {
  ListElem *pElemToDelete = mpHead;
  for (int i = 0; i < iPos; ++i) {
    pElemToDelete = pElemToDelete->mpNext;
  }
  //..

iPos 大于或等于列表中的节点数时,可以调用未定义的行为。

该功能可以通过以下方式实现

bool delPos( size_t iPos ) 
{
    ListElem **pElemToDelete = &mpHead;

    for ( ; pElemToDelete != nullptr && iPos != 0; --iPos )
    {
         pElemToDelete = &( *pElemToDelete )->mpNext;
    }

    bool success = pElemToDelete != nullptr;

    if ( success )
    {
        ListElem *tmp  = *pElemToDelete;
        *pElemToDelete = ( *pElemToDelete )->mpNext;
        delete tmp;
    }

    return success;
}

现在实现第二个功能并不难。我假设结束位置不包含在已删除节点的范围内。

bool delPos( size_t iStart, size_t iEnd ) 
{
    bool success = iStart < iEnd;

    if ( success )
    {
        ListElem **pElemToDelete = &mpHead;

        size_t i = 0;

        for ( ; pElemToDelete != nullptr && i != iStart; ++i )
        {
            pElemToDelete = &( *pElemToDelete )->mpNext;
        }

        success = pElemToDelete != nullptr;

        if ( success )
        {
            for ( ; pElemToDelete != nullptr && i != iEnd; i++ )
            {
                ListElem *tmp  = *pElemToDelete;
                *pElemToDelete = ( *pElemToDelete )->mpNext;
                delete tmp;
            }
        }
    }

    return success;
}

这是一个演示程序。

#include <iostream>

class List
{
private:
    struct ListElem
    {
        int data;
        ListElem *mpNext;
    } *mpHead = nullptr;
public: 
    List() = default;

    void pushFront( int );

    bool delPos( size_t );
    bool delPos( size_t, size_t );

    std::ostream & printList( std::ostream & = std::cout ) const;
};


void List::pushFront( int data )
{
    mpHead = new ListElem { data, mpHead };
}

bool List::delPos( size_t iPos ) 
{
    ListElem **pElemToDelete = &mpHead;

    for ( ; pElemToDelete != nullptr && iPos != 0; --iPos )
    {
         pElemToDelete = &( *pElemToDelete )->mpNext;
    }

    bool success = pElemToDelete != nullptr;

    if ( success )
    {
        ListElem *tmp  = *pElemToDelete;
        *pElemToDelete = ( *pElemToDelete )->mpNext;
        delete tmp;
    }

    return success;
}

bool List::delPos( size_t iStart, size_t iEnd ) 
{
    bool success = iStart < iEnd;

    if ( success )
    {
        ListElem **pElemToDelete = &mpHead;

        size_t i = 0;

        for ( ; pElemToDelete != nullptr && i != iStart; ++i )
        {
            pElemToDelete = &( *pElemToDelete )->mpNext;
        }

        success = pElemToDelete != nullptr;

        if ( success )
        {
            for ( ; pElemToDelete != nullptr && i != iEnd; i++ )
            {
                ListElem *tmp  = *pElemToDelete;
                *pElemToDelete = ( *pElemToDelete )->mpNext;
                delete tmp;
            }
        }
    }

    return success;
}

std::ostream & List::printList( std::ostream &os ) const
{
    for ( ListElem *current = mpHead; current != nullptr; current = current->mpNext )
    {
        os << current->data << ' ';
    }

    return os << "nullptr";
}

int main() 
{
    List lst;

    const int N = 10;

    for ( int i = 0; i < N; i++ ) lst.pushFront( i );

    lst.printList() << '\n';

    lst.delPos( 0 );

    lst.printList() << '\n';

    lst.delPos( 8 );

    lst.printList() << '\n';

    lst.delPos( 3, 5 );

    lst.printList() << '\n';

lst.delPos( 0, 6 );

lst.printList() << '\n';
}

它的输出是

9 8 7 6 5 4 3 2 1 0 nullptr
8 7 6 5 4 3 2 1 0 nullptr
8 7 6 5 4 3 2 1 nullptr
8 7 6 3 2 1 nullptr
nullptr

【讨论】:

  • 谢谢 :) 我明白你的意思,但双指针对我来说非常混乱。但我明白你的意思,这对我的思考过程很有帮助
  • 我只用一个指针尝试它,但不知何故它对我不起作用..也许我的大脑只是不明白。它几乎与一个指针相同,对吗?没有双
  • @MoFug 使用一个指针,函数将无法正常工作。他们至少无法更改头节点。
  • 啊,我的意思是我可以在没有双指针的情况下做到这一点吗?我的意思是我可以工作.. 但不知何故我的输出显示了一个例如我得到 6 5 4 3 2 1 并从 1 到 2 位置删除它显示我作为这样的输出 6 858124 3 2 1 nulltpr。不知何故,它在已删除的节点之间添加了一些东西。你知道为什么吗?如果我只是设置 ``` storefirst->mpNext = pElemToDelete;``` 并调整其余代码,我会稍微更改您的代码 ``` ListElem *pElemToDelete = mpHead;``` 并在第二个之后添加 ListElem* storefirst = pElemToDelete; .
猜你喜欢
  • 1970-01-01
  • 2014-08-20
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
相关资源
最近更新 更多