当指向上一个节点的指针不可用时,从单个链接列表中删除中间节点

时间:2020-03-05 18:55:06  来源:igfitidea点击:

当我们拥有的唯一可用信息是指向要删除的节点的指针而不是指向上一个节点的指针时,是否可以删除单个链表中的中间节点?删除的节点。

解决方案

回答

是的,但是我们不能取消链接。如果我们不关心内存损坏,请继续;-)

回答

如果我们想保持列表的可遍历性,则不需要。我们需要更新上一个节点以链接到下一个节点。

无论如何,我们怎么会遇到这种情况?我们要做什么才能使我们提出这个问题?

回答

是的,但是将其删除后,列表将被打断。

在这种情况下,请再次遍历该列表并获取该指针!通常,如果我们问的是这个问题,那么我们所做的事情可能存在错误。

回答

最初的建议是进行以下转换:

a-> b-> c

到:

一个->,c

如果我们保留信息,例如,从节点地址到下一个节点地址的映射,则可以在下次修复链以遍历列表。如果需要在下一次遍历之前删除多个项目,则需要跟踪删除顺序(即更改列表)。

标准解决方案是考虑其他数据结构,例如跳过列表。

回答

我们必须沿列表前进才能找到上一个节点。这将导致删除一般O(n ** 2)。如果我们是唯一执行删除操作的代码,则在实践中可能会做得更好,方法是缓存上一个节点,然后在该位置开始搜索,但这是否有用取决于删除模式。

回答

为了到达上一个列表项,我们需要从头开始遍历该列表,直到找到带有指向当前项目的" next"指针的条目。然后,我们将拥有一个指向每个项目的指针,只需将" previous-> next"设置为" current-> next",然后删除" current",便可以将其从列表中删除。

编辑:Kimbo在不到一分钟的时间内击败了我!

回答

也许要进行软删除? (即,在节点上设置"已删除"标志),以后可以根据需要清理列表。

回答

一种方法是为数据插入空值。每当遍历列表时,我们都会跟踪上一个节点。如果找到空数据,请修复列表,然后转到下一个节点。

回答

我们可以执行延迟的取消链接,在该链接中,我们可以设置带有标志的要从列表中取消链接的节点,然后在下一次正确遍历时将其删除。设置为取消链接的节点将需要由爬网列表的代码正确处理。

我想我们也可以从头开始再次遍历列表,直到找到指向列表中项目的东西为止。这几乎不是最佳选择,但至少比延迟脱链更好。

通常,我们应该知道指向刚来自的项目的指针,并且应该将其传递给它。

(编辑:艾克,随着我花了很长时间才给出一个完整的答案,三个专长的人几乎涵盖了我要提到的所有要点。:()

回答

唯一明智的方法是使用几个指针遍历列表,直到前一个找到要删除的节点,然后使用尾随指针更新下一个字段。

如果要有效地从列表中删除随机项目,则需要对其进行双重链接。但是,如果要从列表的开头取出项目,然后在列表的末尾添加项目,则无需双重链接整个列表。单独链接列表,但使列表上最后一项的下一个字段指向列表上的第一项。然后使列表" head"指向尾项(而不是head)。这样就很容易将其添加到列表的末尾或者从头部删除。

回答

让我们假设一个具有以下结构的列表

A-> B-> C-> D

如果我们只有指向B的指针并想删除它,则可以执行以下操作

tempList = B->next;
*B = *tempList;
free(tempList);

该列表将如下所示

A-> B-> D

但是B会保留C的旧内容,从而有效地删除B中的内容。如果其他一些代码持有指向C的指针,则此操作将无效。如果我们尝试删除节点D,它也将无效。如果要执行这种操作,则需要使用未真正使用的虚拟尾节点来构建列表,以确保没有有用的节点的下一个指针为NULL。这对于节点中存储的数据量较小的列表也更有效。像这样的结构

struct List { struct List *next; MyData *data; };

会好的,但是那是

struct HeavyList { struct HeavyList *next; char data[8192]; };

会有点累。

回答

你是名单的首长吧?我们只需遍历它。

假设列表由" head"指向,要删除它的节点由" del"指向。

C风格的伪代码(点在C中为->):

prev = head
next = prev.link

while(next != null)
{
  if(next == del)
  {
    prev.link = next.link;
    free(del);
    del = null;
    return 0;
  }
  prev = next;
  next = next.link;
}

return 1;

回答

这绝对是测验,而不是实际的问题。但是,如果允许我们做一些假设,则可以在O(1)时间内解决。为此,列表指向的限制必须是可复制的。算法如下:

我们有一个看起来像这样的列表:...-> Node(i-1)-> Node(i)-> Node(i + 1)-> ...,我们需要删除Node(i)。

  • 将数据(不是指针,即数据本身)从Node(i + 1)复制到Node(i),列表如下所示:...-> Node(i-1)-> Node(i + 1)->节点(i + 1)-> ...
  • 将第二个Node(i + 1)的NEXT复制到一个临时变量中。
  • 现在删除第二个节点(i + 1),它不需要指向上一个节点的指针。

伪代码:

void delete_node(Node* pNode)
{
    pNode->Data = pNode->Next->Data;  // Assume that SData::operator=(SData&) exists.
    Node* pTemp = pNode->Next->Next;
    delete(pNode->Next);
    pNode->Next = pTemp;
}

麦克风。

回答

给定

A-> B-> C-> D

以及指向项目B的指针,我们可以通过以下方式将其删除
1.释放属于B成员的任何记忆
2.将C的内容复制到B(包括其"下一个"指针)
3.删除整个项目C

当然,我们必须注意边缘情况,例如处理一项清单。

现在那里有B,我们有了C,并且曾经是C的存储已释放。

回答

以下代码将创建一个LL,n然后要求用户将指针提供给要删除的节点。删除后将打印列表
它的作用与通过在要删除的节点之后复制节点,在要删除的节点上复制节点,然后删除要删除的节点的下一个节点来执行的操作相同。
IE

A B C D

复制c到b并释放c,结果是

c一d

struct node  
{
    int data;
    struct node *link;
 };

void populate(struct node **,int);

void delete(struct node **);

void printlist(struct node **);

void populate(struct node **n,int num)
{

    struct node *temp,*t;
    if(*n==NULL)
    {
        t=*n;
        t=malloc(sizeof(struct node));
        t->data=num;
        t->link=NULL;
        *n=t;
    }
    else
    {
        t=*n;
        temp=malloc(sizeof(struct node));
        while(t->link!=NULL)
            t=t->link;
        temp->data=num;
        temp->link=NULL;
        t->link=temp;
    }
}

void printlist(struct node **n)
{
    struct node *t;
    t=*n;
    if(t==NULL)
        printf("\nEmpty list");

    while(t!=NULL)
    {
        printf("\n%d",t->data);
        printf("\t%u address=",t);
        t=t->link;
    }
}

void delete(struct node **n)
{
    struct node *temp,*t;
    temp=*n;
    temp->data=temp->link->data;
    t=temp->link;
    temp->link=temp->link->link;
    free(t);
}    

int main()
{
    struct node *ty,*todelete;
    ty=NULL;
    populate(&ty,1);
    populate(&ty,2);
    populate(&ty,13);
    populate(&ty,14);
    populate(&ty,12);
    populate(&ty,19);

    printf("\nlist b4 delete\n");
    printlist(&ty);

    printf("\nEnter node pointer to delete the node====");
    scanf("%u",&todelete);
    delete(&todelete);

    printf("\nlist after delete\n");
    printlist(&ty);

    return 0;
}

回答

void delself(list *list)
{
   /*if we got a pointer to itself how to remove it...*/
   int n;

   printf("Enter the num:");

   scanf("%d",&n);

   while(list->next!=NULL)
   {
       if(list->number==n) /*now pointer in node itself*/
       {
           list->number=list->next->number;
           /*copy all(name,rollnum,mark..) data of next to current, disconect its next*/
           list->next=list->next->next;
       }
       list=list->next;
   }
}

回答

void delself(list *list)
{
   /*if we got a pointer to itself how to remove it...*/
   int n;

   printf("Enter the num:");
   scanf("%d",&n);

   while(list->next!=NULL)
   {
      if(list->number==n) /*now pointer in node itself*/
      {
         list->number=list->next->number;   /*copy all(name,rollnum,mark..)
                             data of next to current, disconnect its next*/
         list->next=list->next->next;
      }
      list=list->next;
   }
}

回答

如果具有链接列表A-> B-> C-> D和指向节点B的指针。如果必须删除此节点,则可以将节点C的内容复制到B,将节点D的内容复制到C并删除D。对于单链列表,我们无法删除该节点,因为如果这样做,节点A也将丢失。虽然在双向链表的情况下我们可以回溯到A。

我对吗?

回答

不可能。

有一些模仿删除的技巧。

但是,这些都不会真正删除指针指向的节点。

如果我们有指向列表中节点的外部指针,则删除后一个节点并将其内容复制到要删除的实际节点的流行解决方案会产生副作用。