【问题标题】:How to pop element from tail in linked list?如何从链表的尾部弹出元素?
【发布时间】:2013-11-12 08:18:38
【问题描述】:

我正在尝试使用各种推送和弹出功能来学习链表,但我无法从链表的尾部弹出元素。谁能帮我解决popBack函数?

我尝试过类似的方法:

typedef struct
{
  float val;
}data;

typedef struct nodePtr
{
  struct nodePtr *next;
  data *d;
}node;

typedef struct
{
  node *head;
  node *tail;
}linkList;

linkList* createlinkList()
{
        linkList *ll = (linkList*)malloc(sizeof(linkList));
        ll->head = NULL;
        ll->tail = NULL;
        return ll;
}

node* createNode(data *d)
{
    node *nd = (node*)malloc(sizeof(node));
    nd-> d = d;
    nd-> next = NULL;
    return nd;
}

data* createData(float val)
{
    data *iptr = (data*)malloc(sizeof(data));
    iptr->val = val;
    return iptr;
}

void addFront(linkList *ll,data *d)
{
    node *new_node = createNode(d);
    if(ll->head == NULL && ll->tail == NULL )   
    {
        ll->head = new_node;
        ll->tail = new_node;
    }
    else
    {
        new_node->next = ll->head;
        ll->head = new_node;
    }
}

void addBack(linkList *ll,data *d)
{
    node *new_node = createNode(d);
    if(ll->head == NULL && ll->tail == NULL )   
    {
        ll->head = new_node;
        ll->tail = new_node;
    }
    else
    {
        ll->tail->next = new_node;
        ll->tail = new_node;
    }
}

void printList(linkList *ll)
{
    node *temp = ll->head;
    while(temp!=NULL)
    {
        printf("%f\n",temp->d->val);
        temp = temp->next;
        /*if(temp==ll->tail)
        {
            printf("%f\n",temp->d->val);
            break;
        }*/
    }
}

int listSize(linkList *ll)
{
    int size=0; 
    node *count;
    for(count=ll->head;count!=NULL;count=count->next)
    {
            size++;
    }
    return size;
}

data* popFront(linkList *ll)
{
    data *popf;
    popf = ll->head->d;
    node *temp = ll->head;
    ll->head = ll->head->next;
    free(temp);
    return popf;
}

**data* popBack(linkList *ll)
{
    data *popb;
    popb = ll->tail->d;
    while(ll->head->next!=NULL)
    {
        printf("%f\n",ll->head->next->d->val);
        if(ll->head->next==NULL)
        {
            node* temp = ll->head->next;
            free(temp);
        }
    }
    return popb;
}**

int main(int argc, char* argv[])
{
    linkList *ll = createlinkList();
    data *iptr = createData(11.10);
    addFront(ll,iptr);
    data *iptr1 = createData(10.10);
    addFront(ll,iptr1);
    data *iptr2 = createData(12.10);
    addBack(ll,iptr2);
    printList(ll);
    int count = listSize(ll);
    printf("%d\n",count);
    popFront(ll);
    printList(ll);
    popBack(ll);
    printList(ll);
  return 0;
}

【问题讨论】:

  • 你的 if 条件应该检查​​count。另外,别忘了更新tai​​l
  • 没有双指针(prevnext),这将是一个 O(n) 算法,你知道的。也就是说,使用单个指针到指针变量的相当优雅的解决方案是常用的(好吧,也许不常用,但我常用=)

标签: c pointers linked-list


【解决方案1】:

您有一个单链接列表。你需要做几件事。您需要找到链表尾部之前的节点(仅当链表上有2个或更多节点时才存在),并提取尾部(容易找到,您有指向它的指针)。

  • 寻找尾巴
  • 找到尾部的上一个节点
  • 将尾部指向上一个节点
  • 要么将 prev(ious) 设置为 NULL(已删除),要么
  • 将头部设置为 NULL(列表中只有一项)

怎么做?

data* popBack(linkList *ll)
{
    node* prev; //need to find this
    node* iter; //iterator through list
    data *popb;
    if(!ll) return NULL; //list is non-existant
    if(!ll->head) return NULL; //list is empty
    prev=>NULL; //don't have a previous yet.
    iter=ll->head;
    while(iter!=ll->tail)
    {
        prev=iter; //not the tail, there must be a node after this
        iter=iter->next; //not null, could be tail
    }
    //iter==ll->tail, so prev must be either before tail or NULL (only 1 node on list)
    if( prev==NULL ) { ll->head=NULL; }
    else prev->next=NULL;
    printf("%f\n",ll->tail->d->val);
    popb = ll->tail->d;
    free(ll->tail); //free old tail
    ll->tail = prev;  //new tail
    return popb;
}

【讨论】:

    【解决方案2】:

    嘿 rips 来反转链表。

    您可以通过转到最后一个节点来反转链表,将最后一个节点存储在临时节点中,然后反转指针。使用递归使其变得简单。

    if lastbutone->next->next=NULL
    lastbutone= temporary
    
    recursion
    last->next=temporary;
    last=temporary; 
    

    注意最后一个节点和第一个节点,给最后一个节点命名,比如 headptr.. 当你到达第一个节点时,然后将 null 分配给它的下一个节点。

    【讨论】:

      【解决方案3】:
      data* popBack(linkList *ll)
      {
      data *popb;
      popb = ll->tail->d;
      
      node* ptrf = ll->head;
      node* ptre = ll->tail;
      
      if(ptrf == NULL && ptre == NULL){ //no node in the linkList
          return NULL;
      }else if(ptrf == ptre){ //only one node in the linkList
          free(ptre);
          ptrf = ptre = NULL;
          return popb;
      }else { //at least two nodes in the linkList
          while((ptrf->next) != ptre)
          {
              ptrf = ptrf->next;
          }
          free(ptre);
          ptrf->next = NULL;
          ll->tail = ptrf;
          return popb;
      }
      }
      

      【讨论】:

      • 谢谢你们。赞赏。
      • 我还有一个问题。如何反转整个链表?
      猜你喜欢
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 2021-07-23
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      • 2012-09-12
      • 2013-12-21
      相关资源
      最近更新 更多