【问题标题】:LinkedList - Type in C - Accessing FunctionsLinkedList - 输入 C - 访问函数
【发布时间】:2017-10-22 06:47:51
【问题描述】:

出于教学原因,我目前正在 C 中实现 LinkedList。 我快完成了,但现在正在苦苦挣扎,因为 它并没有完全按照它的意图去做

长话短说,我的代码的输出不是我所期望的 - 现在我在大脑中绕着这个转圈有点筋疲力尽。

这是整个实现:

#include  <stdio.h>
#include <stdlib.h>
#include <string.h>

/********** GLOBALS *******************************/
#define DEBUG 0

/********** 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*/
LinkedList init_list() {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);

    LinkedList list;

    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*/
void insert_end(LinkedList *list, int key, char string[]) {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);

    list->size++;                    // increment size of list

    // intialize the new Node
    Node* newN = 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 at end: %d %s %p \n", 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 */
void insert_beginning(LinkedList *list, int key, char string[]) {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);

    list->size++;                    // increment size of list
    Node* oldFirst = list->first;    //get the old first node

    // intialize the new Node
    Node* newN = 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 at beginning: '%d' '%s' '%p' \n", newN->key, newN->string, newN->next);

}

/* Removes the first Node from the list*/
int remove_beginning(LinkedList *list) {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);

    if(list->size <= 0)
       return -1;

    list->size--;

    Node * oldFirst = list->first;
    list->first = oldFirst->next;
    oldFirst = NULL;

    return 0;

}

/* Removes the last Node from the list.*/
int remove_end(LinkedList *list) {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);

    if(list->size <= 0)
        return -1;

    list->size--;                    // decrement list size
    //Node * oldLast = list->last;     // get ref to old last
    //oldLast = NULL;                  // set it null
    //free(oldLast);
    Node * startNode = list->first;
    list->last = NULL;               // set listref last to null

    //find the now new last node..
   Node * newLast = NULL;
   while(startNode->next != NULL) {
        newLast=startNode;
   }

    // if list is not empty now..
    if(list->size > 0)
        list->last = newLast;

    return 0;

}

/* Given a List prints all key/string pairs contained in the list to
the screen*/
int print_list(LinkedList *list) {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);


    if(list->size <=0)
        return -1;

    printf("List.size = %d \n", list->size);

    Node *startN = list->first;  //get first

    printf("Node#%d.string = '%s', .next = '%d' \n",list->first->key, list->first->string, list->first->next->key);

    //iterate through list
    while(startN->next != NULL) {
        printf("Node#%d.string = '%s', .next = '%d' \n",startN->key, startN->string, startN->next->key);
        startN = startN->next;
    }

    return 0;
}

/* Given a List, frees all memory associated with this list. */
void free_list(LinkedList *list) {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);

    if(list != 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 */
char * get_string(LinkedList *list, int key) {

    if(DEBUG)
        printf("%s:%d called \n", __FUNCTION__, __LINE__);

     Node *startN = list->first;  //get first

    //iterate through list
    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_beginning(&list, 2,"im the second" );
    insert_beginning(&list, 3,"im the third" );
    //insert_end(&list, 2, "im the second");
    //insert_end(&list, 3,"im the third");
    //insert_end(&list, 4, "forth here");
    //insert_end(&list, 5, "...and i am last");
    //insert_end(&list, 6, "END");

    print_list(&list);

   // remove_end(&list);
   // remove_beginning(&list);

   // print_list(&list);

   // free_list(&list);

}

这是输出,它不是预期的(但代码编译得很好):

new Node at beginning: '1' 'im the first' '00000000' 
new Node at beginning: '2' 'im the second' '00762EF8' 
new Node at beginning: '3' 'im the third' '00764330' 
List.size = 3 
Node#3.string = 'im the third', .next = '2' 
Node#3.string = 'im the third', .next = '2' 
Node#2.string = 'im the second', .next = '1' 

如您所见,print_list 要么没有正确打印列表,要么列表本身不正确。

  • 我哪里失败了?

与往常一样,我们非常欢迎最佳实践提示,并且来源是公共领域。

【问题讨论】:

  • 顺便说一句,你可以考虑使用循环双链表,这样会更简单。这是一个例子:pastebin.com/mScMkkdy
  • 感谢@0andriy,但它是有意实现单链表而不是双向链表。

标签: c data-structures linked-list pass-by-reference


【解决方案1】:

您的队列实际上是一个堆栈,因为您将事物推到头上,先入后出的顺序。

我刚刚将你的 print_list 函数更改如下;

//iterate through list
do {
    printf("Node#%d.string = '%s', .next = '%p' \n",startN->key, startN->string, startN->next);
    startN = startN->next;
}while(startN != NULL);

我得到这个改变的输出是;

new Node at beginning: '1' 'im the first' '0x0'
new Node at beginning: '2' 'im the second' '0x2003ac40'
new Node at beginning: '3' 'im the third' '0x2004b088'
List.size = 3
Node#3.string = 'im the third', .next = '0x2004b088'
Node#2.string = 'im the second', .next = '0x2003ac40'
Node#1.string = 'im the first', .next = '0x0'

【讨论】:

    【解决方案2】:

    您的问题是您将第一个元素打印了两次。

    这里:

    Node *startN = list->first;
    
    printf("Node#%d.string = '%s', .next = '%d' \n",list->first->key, list->first->string, list->first->next->key);
                                                    ^^^^^^^^^^^
                                               //   Same as startN->key !    
    //iterate through list
    while(startN->next != NULL) {
        printf("Node#%d.string = '%s', .next = '%d' \n",startN->key, startN->string, startN->next->key);
                                                        ^^^^^^^^^^^
                                                  //    So in first loop you print the same again.
    
        startN = startN->next;
    }
    

    我猜你的第二个printf应该是:

        printf("Node#%d.string = '%s', .next = '%d' \n",startN->next->key, startN->next->string, startN->next->key);
                                                               ^^^^^^              ^^^
    

    【讨论】:

      【解决方案3】:

      只需如下更改 print_list 函数即可获得预期结果

      int print_list(LinkedList *list) {
      
      if(DEBUG)
          printf("%s:%d called \n", __FUNCTION__, __LINE__);
      
      
      if(list->size <=0)
          return -1;
      
      printf("List.size = %d \n", list->size);
      
      Node *startN = list->first;  //get first
      
      // This line is not needed because linked list getting traversed in while loop only 
      //printf("Node#%d.string = '%s', .next = '%d' \n",list->first->key, list->first->string, list->first->next->key);
      
      //iterate through list
      // Here use startN != NULL because last node should also be retrieved.
      /* while(startN->next != NULL) {
          printf("Node#%d.string = '%s', .next = '%d' \n",startN->key, startN->string, startN->next->key);
          startN = startN->next;
      }*/
      
      while(startN != NULL) {
          printf("Node#%d.string = '%s', .next = '%d' \n",startN->key, startN->string, startN->next->key);
          startN = startN->next;
       }
      
      return 0;}
      

      【讨论】:

        【解决方案4】:

        我已经清除了错误/缺陷。感谢您的建议,它对我的​​工作帮助很大。我在int remove_end(LinkedList *list)print_list 中存在逻辑缺陷(感谢你们指出!)

        ..这里是整个(工作和测试(希望是干净的))实施:

        #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
        
             /* if only one node.. */
             if(list->size == 1)
                 return startN->string;
        
            /* 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;
        }
        

        输出:

        initializing list...
        ----------------------
        new Node(00C31668) at beginning: 1 'im the first' 00000000 
        ----------------------
        new Node(00C33E88) at end: 2 'im the second' 00000000 
        ----------------------
        new Node(00C34298) at end: 3 'im the third' 00000000 
        ----------------------
        new Node(00C346A8) at end: 4 'forth here' 00000000 
        ----------------------
        List.size = 4 
        Node#1.string = 'im the first', .next = '00C33E88' 
        Node#2.string = 'im the second', .next = '00C34298' 
        Node#3.string = 'im the third', .next = '00C346A8' 
        Node#4.string = 'forth here', .next = '00000000' 
        ----------------------
        delete Node(00C346A8) at end: '4' 'forth here' '00000000' 
        ----------------------
        List.size = 3 
        Node#1.string = 'im the first', .next = '00C33E88' 
        Node#2.string = 'im the second', .next = '00C34298' 
        Node#3.string = 'im the third', .next = '00000000' 
        ----------------------
        delete Node(00C31668) at beginning: '1' 'im the first' '00C33E88' 
        ----------------------
        List.size = 2 
        Node#2.string = 'im the second', .next = '00C34298' 
        Node#3.string = 'im the third', .next = '00000000' 
        ----------------------
        delete Node(00C34298) at end: '3' 'im the third' '00000000' 
        ----------------------
        List.size = 1 
        Node#2.string = 'im the second', .next = '00000000' 
        ----------------------
        string at node with key 2 = 'im the second' 
        ----------------------
        freeing list...
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多