【问题标题】:How to Delete the last element in a linked list in C?如何删除C中链表中的最后一个元素?
【发布时间】:2013-07-28 10:36:52
【问题描述】:

我不知道如何在 c 中删除链表中的第一个和最后一个元素。下面是我的程序,它使用链表。我不知道如何实际删除最后一个元素,但我能找到它。该元素由一个整数和下一个指针组成。如果有人可以帮助我,将不胜感激。

struct ListNode{
    int value;
    struct ListNode *next;
};
typedef struct ListNode Link;

void deleteLast(Link *);
void printList(Link *);
void deleteFirst(Link *);

int main(){
    Link *myList;
 Link *curr, *newlink;
 int i;
    curr = myList;
    for(i = 0; i < 10; i++){

            newlink = (Link*) malloc(1*sizeof(Link));
            newlink->value = i*i;
            curr->next = newlink;
            curr = newlink;
    }

    curr->next = NULL;
    curr = myList->next;
    deleteFirst(curr);
    printList(curr);
    printf("\n");
}
void deleteLast(Link *head)
{
    Link *curr;
    curr = head->next;
    while (curr->next!=NULL)
    {
        curr = curr->next;
    }
     free(curr->next);

    curr->next = NULL;

}
void printList(Link *head){
    Link *curr;
    curr = head->next;

    printf("[");
    if(curr!=NULL){
        printf("%d",curr->value);
        curr = curr->next;
    }

    while(curr != NULL){
        printf(", %d", curr->value);
        curr = curr->next;
    }
    printf("]\n");

}
void deleteFirst(Link *head){
    Link *curr;
    curr = head->next;
    free(curr->value);
    free(curr->next);
    printf("%d\t",curr->value);
}

我尝试的任何方法都不起作用,请你帮帮我。

【问题讨论】:

  • 你先删除也是错误的,你必须得到我的链接**而不是链接*
  • 我从一个答案开始,但意识到上面的代码在尝试删除任何列表元素之前很久就被严重破坏了。特别是myList 从未初始化,但curr 设置为它可能具有的任何垃圾值;然后写入curr-&gt;next,即使curr 是最初可能在myList 中的任何垃圾值的副本。解决此问题后,请查看现有问题,例如 stackoverflow.com/questions/2906636/…

标签: c list dynamic linked-list allocation


【解决方案1】:

您的代码中有很多错误。

  • 创建列表时:
    • 您不必强制转换 malloc 的返回值
    • 您正在执行curr-&gt;next = newlink; 其中 curr = myList 具有初始化值。您可以将循环更改为
  Link *myList = NULL;
  Link *curr, *newlink;
  int i;

  curr = myList;
  for(i = 0; i < 10; i++){

    newlink = malloc(1*sizeof(Link));
    newlink->value = i*i;
    if (curr != NULL)
      curr->next = newlink;
    else
      myList = newlink;
    curr = newlink;
  }
  • 当您删除最后一个元素时,这就是它不起作用的原因
  Link  *curr;

  curr = head->next;   
  while (curr->next != NULL) {
    head = curr;
    curr = curr->next;
  }

  free(head->next);
  head->next = NULL;
  • 当您想要删除列表的第一个元素时
    • 您不必释放字段值,因为您没有使用 malloc 分配它
    • 即使删除列表的第一个元素,也不会更改主列表开头的值。这就是为什么您必须将Link** 作为参数
void deleteFirst(Link **head){
  Link *curr;

  curr = (*head)->next;
  free(*head);
  *head = curr;
}

您可以通过提供列表开头的地址从主函数调用此函数:

  deleteFirst(&myList);
  deleteLast(myList);
  printList(myList);

当然,在所有函数中,您必须检查列表中是否至少有一些值,而不是空指针NULL

【讨论】:

    【解决方案2】:
    #include <stdint.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct node Node;
    struct node{
        int element;
        Node *next;
    };
    
    Node* head = NULL;
    
    bool put(int data)
    {
        bool retVal = false;
    
        Node* temp;
    
        do
        {
            if (head == NULL)
            {
                head = malloc(sizeof(Node));
    
                if (head)
                {
                    printf("New head created\n");
                    head->element = data;
                    head->next = NULL;
                    printf("Element %d stored\n", data);
    
                    retVal = true;
                    break;
                }           
                else
                {           
                    printf("Could not create new head\n");
                    break;
                }   
            }
    
            temp = head;
            while (temp->next != NULL)
            {
                temp = temp->next;
            }
    
            temp->next = malloc(sizeof(Node));
            temp->next->element = data;
            temp->next->next = NULL;
    
            printf("Element %d stored\n", data);
    
            retVal = true;
            break;
    
        } while(1);
    
        return retVal;
    }
    
    
    
    bool get(int *pData)
    {
        bool retVal = false;
        Node* temp;
    
        if (head != NULL)
        {
            retVal = true;
            Node *prevNode = head;
    
            temp = prevNode;
            while (temp->next)
            {
                prevNode = temp;
                temp = temp->next;
            }
    
            *pData = temp->element;
            printf("Element %d retrieved\n", *pData);
    
            free(temp);
            printf("Node freed\n");
    
            if (temp == head)
            {
                head = NULL;
            }
            else
            {
                prevNode->next = NULL;
            }   
        }
    
        return retVal;
    }
    
    
    int main(void)
    {
        int retrievedNum;
        int num;
    
        for (num = 0; num < 5; num++)
        {
            put(num);
        }
    
        printf("\n");
    
        for (num = 0; num < 6; num++)
        {
            get(&retrievedNum);
        }
    
        put(num);
    
        get(&retrievedNum);
    
        printf("Element retrieved: %d\n", retrievedNum);
    
        return 1;
    }
    

    【讨论】:

      【解决方案3】:

      此代码将用于删除链接列表中的最后一个元素:

      void dellast()
      
      {
      
      r=head;
      
      struct node* z;
      do
      {
          z=r;
          r=r->next;
          if(r->next==NULL)
          {
              z->next=NULL;
              free(r->next);
          }   
      }while(z->next!=NULL);
      }
      

      代码的工作方式如下:

      跟踪当前节点及其前一个节点。

      如果 current->next==NULL 表示它是最后一个节点。

      previous->next=NULL 并释放当前节点也是如此

      【讨论】:

        【解决方案4】:

        我用 C 语言制作了我自己的(单独的)LinkedList 示例,它被证明是有效的:

        #include  <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        /********** GLOBALS *******************************/
        #define OK 0
        #define ERROR -1
        
        /********** STRUCT AND TYPES DEFINTIONS ***********/
        /* a node with key, data and reference to next node*/
        typedef struct Node {
            int key;
            char string[1024];
            struct Node *next;  // pointer to next node
        } Node;
        
        /* the actual linked list: ref to first and last Node, size attribute */
        typedef struct LinkedList {
            struct Node *first;
            struct Node *last;
            int size;
        } LinkedList;
        
        /********** FUNCTION HEADERS **********************/
        LinkedList* init_list();
        void insert_end(LinkedList *list, int key, char string[]);
        void insert_beginning(LinkedList *list, int key, char string[]);
        int remove_end(LinkedList *list);
        int remove_beginning(LinkedList *list);
        int print_list(LinkedList *list);
        void free_list(LinkedList *list);
        char * get_string(LinkedList *list, int key);
        
        /*********** FUNCTION DEFINITIONS ***************/
        
        /**
         * init_list Returns an appropriately (for an empty list) initialized struct List
         *
         * @return LinkedList *         ..ptr to the newly initialized list
         */
        LinkedList * init_list() {
            printf("initializing list...\n");
        
            LinkedList *list = (LinkedList*) malloc(sizeof(LinkedList));
        
            list->first = NULL;
            list->last = NULL;
            list->size = 0;
        
            return list;
        }
        
        /**
         * Given a List, a key and a string adds a Node containing this
         * information at the end of the list
         *
         * @param list      LinkedList *    ..ptr to LinkedList
         * @param key       int             .. key of the Node to be inserted
         * @param string    char[]          .. the string of the Node to be inserted
         */
        void insert_end(LinkedList *list, int key, char string[]) {
            printf("----------------------\n");
        
            list->size++;                    // increment size of list
        
            // intialize the new Node
            Node* newN = (Node*) malloc(sizeof(Node));
            newN->key = key;
            strcpy(newN->string, string);
            newN->next = NULL;
        
            Node* oldLast = list->last;      // get the old last
            oldLast->next = newN;          // make new Node the next Node for oldlast
            list->last = newN;              // set the new last  in the list
        
            printf("new Node(%p) at end: %d '%s' %p \n", newN, newN->key, newN->string,newN->next);
        }
        
        /**
         * Given a List, a key and a string adds a Node, containing
         * this information at the beginning of the list
         *
         * @param list      LinkedList *    ..ptr to LinkedList
         * @param key       int             .. key of the Node to be inserted
         * @param string    char[]          .. the string of the Node to be inserted
         */
        void insert_beginning(LinkedList *list, int key, char string[]) {
            printf("----------------------\n");
        
            list->size++;                    // increment size of list
            Node* oldFirst = list->first;    //get the old first node
        
            /* intialize the new Node */
            Node* newN = (Node*) malloc(sizeof(Node));
            newN->key = key;
            strcpy(newN->string, string);
            newN->next = oldFirst;
        
            list->first = newN;              // set the new first
        
            /* special case: if list size == 1, then this new one is also the last one */
            if (list->size == 1)
                list->last = newN;
        
            printf("new Node(%p) at beginning: %d '%s' %p \n", newN, newN->key,newN->string, newN->next);
        }
        
        /**
         * Removes the first Node from the list
         *
         * @param list      LinkedList *        .. ptr to the List
         *
         * @return OK | ERROR
         */
        int remove_beginning(LinkedList *list) {
            printf("----------------------\n");
        
            if (list->size <= 0)
                return ERROR;
        
            list->size--;
        
            Node * oldFirst = list->first;
        
            printf("delete Node(%p) at beginning: '%d' '%s' '%p' \n", oldFirst,oldFirst->key, oldFirst->string, oldFirst->next);
        
            free(list->first);          //free it
            list->first = oldFirst->next;
            oldFirst = NULL;
        
            return OK;
        }
        
        /**
         * Removes the last Node from the list.
         *
         * @param list      LinkedList *        .. ptr to the List
         *
         * @return OK | ERROR
         */
        int remove_end(LinkedList *list) {
            printf("----------------------\n");
        
            /* special case #1 */
            if (list->size <= 0)
                return ERROR;
        
            /* special case #2 */
            if (list->size == 1) {
                free(list->first);
                list->first = NULL;
                list->last = NULL;
                return OK;
            }
        
            printf("delete Node(%p) at end: '%d' '%s' '%p' \n", list->last,list->last->key, list->last->string, list->last->next);
        
            list->size--;           // decrement list size
            Node * startNode = list->first;
        
            /* find the new last node (the one before the old last one); list->size >= 2 at this point!*/
            Node * newLast = startNode;
            while (newLast->next->next != NULL) {
                newLast = newLast->next;
            }
        
            free(newLast->next);    //free it
            newLast->next = NULL;   //set to NULL to denote new end of list
            list->last = newLast;   // set the new list->last
        
            return OK;
        }
        
        /**
         * Given a List prints all key/string pairs contained in the list to
         * the screen
         *
         * @param list      LinkedList *        .. ptr to the List
         *
         * @return  OK | ERROR
         */
        int print_list(LinkedList *list) {
        
            printf("----------------------\n");
        
            if (list->size <= 0)
                return ERROR;
        
            printf("List.size = %d \n", list->size);
        
            Node *startN = list->first;  //get first
        
            /* iterate through list and print contents */
            do {
                printf("Node#%d.string = '%s', .next = '%p' \n", startN->key,startN->string, startN->next);
                startN = startN->next;
            } while (startN != NULL);
        
            return OK;
        }
        
        /**
         * Given a List, frees all memory associated with this list.
         *
         * @param list      LinkedList *        ..ptr to the list
         */
        void free_list(LinkedList *list) {
            printf("----------------------\n");
            printf("freeing list...\n");
        
            if (list != NULL && list->size > 0) {
                Node * startN = list->first;
                Node * temp = list->first;
        
                do {
                    free(temp);
                    startN = startN->next;
                    temp = startN;
                } while (startN != NULL);
        
                free(list);
            }
        }
        
        /**
         * Given a List and a key, iterates through the whole List and returns
         * the string of the first node which contains the key
         *
         * @param list      LinkedList *        ..ptr to the list
         * @param key       int                 .. the key of the Node to get the String from
         *
         * @return OK | ERROR
         */
        char * get_string(LinkedList *list, int key) {
            printf("----------------------\n");
        
            Node *startN = list->first;  //get first
        
            /* iterate through list and find Node where node->key == key */
            while (startN->next != NULL) {
                if (startN->key == key)
                    return startN->string;
                else
                    startN = startN->next;
            }
        
            return NULL;
        }
        
        /*************** MAIN **************/
        int main(void) {
        
            LinkedList *list = init_list();
        
            insert_beginning(list, 1, "im the first");
            insert_end(list, 2, "im the second");
            insert_end(list, 3, "im the third");
            insert_end(list, 4, "forth here");
        
            print_list(list);
            remove_end(list);
            print_list(list);
            remove_beginning(list);
            print_list(list);
            remove_end(list);
            print_list(list);
            printf("string at node with key %d = '%s' \n",2,get_string(list, 2));
            free_list(list);
        
            return OK;
        }
        

        希望这个实现示例有所帮助。

        【讨论】:

          猜你喜欢
          • 2015-06-29
          • 1970-01-01
          • 2017-04-09
          • 1970-01-01
          • 1970-01-01
          • 2014-10-25
          • 2017-01-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多