1. 程式人生 > >簡單的通用連結串列實現

簡單的通用連結串列實現

最近專案需要用到連結串列, 並且是建立三個不同的專用連結串列,為了對程式碼加以簡化,特採用通用連結串列來實現程式碼功能!

本連結串列是在linux下執行的,因此含有部分系統函式。

本人對指標理解較為粗糙,不能保證程式碼正確性,僅作自己總結而用!

程式碼未加封裝,只有簡單的實現函式。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>


typedef struct listnode
{
    struct listnode *next;
    struct listnode *prev;
    void            *data;
}List;


//新建連結串列頭
List *createNode(void)
{
    List *head = (List *)malloc(sizeof(List));
    if(NULL == head)
    {
        printf("Usage : malloc error !\n");
        return NULL;
    }

    head->next = head->prev = head;

    return head;
}

//尾插法
List *tailInsert(List *head, void *data)
{
    List *node = (List *)malloc(sizeof(List));
    if(NULL == node)
    {
        printf("Usage : malloc error !\n");
        return NULL;
    }
    node->data = data;

    head->prev->next = node;
    node->prev = head->prev;
    head->prev = node;
    node->next = head;

    return head;
}

//摧毀連結串列
void destroyList(List **head)
{
    List *tmp = NULL;
    List *next = NULL;
    if((*head)->next == *head)
    {
        return;
    }
    for(tmp=*head; tmp->next!=*head; tmp=next)
    {
        next = tmp->next;
        free(tmp);
    }
    *head = NULL;
}

//按compare函式來檢索連結串列節點
List *searchList(List *head, void *key, bool (*compare)(void *, void *))
{
    List *ptr = head;
    while(ptr->next != head)
    {
        ptr = ptr->next;
        if(compare(ptr->data, key))
        {
            return ptr;
        }
    }

    return NULL;
}

//刪除compare函式檢索到的節點
List *deleteList(List *head, void *key, bool(*compare)(void *, void*))
{
    List *ptr = head;
    while(ptr->next != head)
    {
        ptr = ptr->next;
        if(compare(ptr->data, key))
        {
            ptr->prev->next = ptr->next;
            ptr->next->prev = ptr->prev;
            free(ptr);
            break;
        }
    }

    return head;
}

//列印連結串列
void printList(List *head, void (*print)(void *))
{
    List *ptr = head;
    while(ptr->next != head)
    {
        ptr = ptr->next;
        print(ptr->data);
    }
}

//把連結串列存入檔案
void saveList(List *head, const char *filename, size_t size)
{
    int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0777);
    if(-1 == fd)
    {
        printf("Usage : open error !\n");
        return;
    }

    List *ptr = head;
    while(ptr->next != head)
    {
        ptr = ptr->next;
        write(fd, ptr->data, size);
    }
    close(fd);

    destroyList(&head);
}

//從檔案讀入連結串列
List *readList(const char *filename, size_t size)
{
    int fd, ret;
    List *head = createNode();

    if(access(filename, F_OK) != 0)
    {
        close(open(filename, O_CREAT | O_APPEND, 0777));
    }
    fd = open(filename, O_RDONLY);
    if(-1 == fd)
    {
        printf("Usage : open error !\n");
        return NULL;
    }
    while(1)
    {
        void *data;
        data = malloc(size);
        ret = read(fd, data, size);
        if(0 == ret)
        {
            break;
        }
        tailInsert(head, data);
    }
    close(fd);

    return head;
}

簡單測試:

typedef struct action
{
    char name[20];
    int id;
}action_t;

//比較函式
bool compare(void *data, void *key)
{
    action_t *act = (action_t *)data;
    int id = (int)key;
    if(act->id == id)
    {
        return true;
    }
    return false;
}

//列印函式
void print(void *data)
{
    action_t *act = (action_t *)data;
    printf("id   = %d\t", act->id);
    printf("name = %s\n", act->name);
}


int main(void)
{
    char *filename = "action.txt";

    action_t test1 = {"zhao", 1};
    action_t test2 = {"qian", 2};
    action_t test3 = {"yang", 3};
    action_t test4 = {"ling", 4};
    action_t test5 = {"zhou", 5};

    List *head = createNode();
    tailInsert(head, (void *)(&test1));
    tailInsert(head, (void *)(&test2));
    tailInsert(head, (void *)(&test3));
    tailInsert(head, (void *)(&test4));
    tailInsert(head, (void *)(&test5));

    printList(head, print);

    //存入檔案
    saveList(head, filename, sizeof(action_t));

    //從檔案讀取
    List *list = readList(filename, sizeof(action_t));
    if(deleteList(list, (void *)1, compare))
    {
        printf("刪除id為1的節點,成功則列印!\n");
    }
    //檢驗是否刪除成功
    printList(list, print);

    return 0;
}