代码之家  ›  专栏  ›  技术社区  ›  matcheek

循环单链表在C语言中的优雅实现?

  •  9
  • matcheek  · 技术社区  · 14 年前

    经过经典的数据结构,在链表上停下来了,刚实现了一个循环的单链表,但我印象深刻的是,这个链表可以用更优雅的方式表达,特别是删除节点功能。 考虑到效率和代码可读性,有人能为单独链接的循环列表提供一个更简洁和高效的解决方案吗?

    #include <stdio.h>
    #include <stdlib.h>
    
    
    struct node{
        struct node* next;
        int value;
    };
    
    
    struct list{
        struct node* head;
    };
    
    
    struct node* init_node(int value){
        struct node* pnode;
        if (!(pnode = (struct node*)malloc(sizeof(struct node)))){
            return NULL;
        }
        else{
            pnode->value = value;   
        }
        return pnode;
    }
    
    struct list* init_list(){
        struct list* plist;
        if (!(plist = (struct list*)malloc(sizeof(struct list)))){
            return NULL;        
        }
        plist->head = NULL;
        return plist;
    }
    
    
    void remove_node(struct list*a plist, int value){
    
        struct node* current, *temp;
        current = plist->head;
        if (!(current)) return; 
        if ( current->value == value ){
            if (current==current->next){
                plist->head = NULL; 
                free(current);
            }
            else {
                temp = current;
                do {    
                    current = current->next;    
                } while (current->next != plist->head);
    
                current->next = plist->head->next;
                plist->head = current->next;
                free(temp);
            }
        }
        else {
            do {
                if (current->next->value == value){
                    temp = current->next;
                    current->next = current->next->next;
                    free(temp);
                }
                current = current->next;
            } while (current != plist->head);
        }
    }
    
    void print_node(struct node* pnode){
        printf("%d %p %p\n", pnode->value, pnode, pnode->next); 
    }
    void print_list(struct list* plist){
    
        struct node * current = plist->head;
    
        if (!(current)) return;
        if (current == plist->head->next){
            print_node(current);
        }
        else{
            do {
                print_node(current);
                current = current->next;
    
            } while (current != plist->head);
        }
    
    }
    
    void add_node(struct node* pnode,struct list* plist){
    
        struct node* current;
        struct node* temp;
        if (plist->head == NULL){
            plist->head = pnode;
            plist->head->next = pnode;
        }
        else {
            current = plist->head;
            if (current == plist->head->next){
                plist->head->next = pnode;
                pnode->next = plist->head;      
            }
            else {
                while(current->next!=plist->head)
                    current = current->next;
    
                current->next = pnode;
                pnode->next = plist->head;
            }
    
        }
    }
    
    4 回复  |  直到 8 年前
        1
  •  5
  •   pitti    14 年前
        2
  •  2
  •   Fabian Giesen    14 年前

    struct node* get_sentinel(struct list* plist)
    {
        // use &plist->head itself as sentinel!
        // (works because struct node starts with the next pointer)
        return (struct node*) &plist->head;
    }
    
    struct list* init_list(){
        struct list* plist;
        if (!(plist = (struct list*)malloc(sizeof(struct list)))){
            return NULL;        
        }
        plist->head = get_sentinel(plist);
        return plist;
    }
    
    void add_node_at_front(struct node* pnode,struct list* plist){
        pnode->next = plist->head;
        plist->head = pnode;
    }
    
    void add_node_at_back(struct node* pnode,struct list* plist){
        struct node *current, *sentinel = get_sentinel(plist);
    
        // search for last element
        current = plist->head;
        while (current->next != sentinel)
            current = current->next;
    
        // insert node
        pnode->next = sentinel;
        current->next = pnode;
    }
    
    void remove_node(struct list* plist, int value){
        struct node **prevnext, *sentinel = get_sentinel(plist);
        prevnext = &plist->head; // ptr to next pointer of previous node
        while (*prevnext != sentinel) {
            struct node *current = *prevnext;
            if (current->value == value) {
                *prevnext = current->next; // remove current from list
                free(current); // and free it
                break; // we're done!
            }
            prevnext = &current->next;
        }
    }
    
    void print_list(struct list* plist){
        struct node *current, *sentinel = get_sentinel(plist);
        for (current = plist->head; current != sentinel; current = current->next)
            print_node(current);
    }
    
        3
  •  1
  •   uesp    14 年前

        4
  •  0
  •   KeyC0de    8 年前

    Node* createCircularLList(int size)
    {
        Node *it; // to iterate through the LList
        Node *head;
    
        // Create the head /1st Node of the list
        head = it = (Node*)malloc(sizeof(Node));
        head->id = 1;
    
        // Create the remaining Nodes (from 2 to size)
        int i;
        for (i = 2; i <= size; ++i) {
            it->next = (Node*)malloc(sizeof(Node)); // create next Node
            it = it->next;                          // point to it
            it->id = i;                             // assign its value / id
            if (i == 2)
                head->next = it; // head Node points to the 2nd Node
        }
        // close the llist by having the last Node point to the head Node
        it->next = head;
    
        return head;    // return pointer to start of the list
    }
    

    Node

    typedef struct Node {
        int id;
        struct Node *next;
    } Node;