链表(C语言实现)

来源:互联网 发布:ubuntu命令行乱码 编辑:程序博客网 时间:2024/04/20 21:04

昨天去面试了一次,发现连链表的操作都不会了,链表的操作我还是会的,只奈有一段时间没有敲 c/c++ 的练习代码,一直想把 Qt 学好,到最后我连一个链表的操作都无从下手了,我想以后每天都得练习一下算法和数据结构方面的代码以保持我的编程思维。

下面我用 c 语言把链表的基本操作实现了一遍,节点数据的信息是「编号」、「姓名」和「年龄」,实现的功能有「链表的创建」「链表初始化」、「插入节点」、「链表的遍历」、「链表的销毁」、「查询节点」、「删除节点」,这里我就把这些函数贴在这里,做一个笔记,以后也可以查看。

定义数据结构:

typedef struct Person {    int number;    char name[50];    int age;} Person_t;typedef struct MLGB {    Person_t monster;    struct MLGB *next;} MLGB_t;typedef struct LinkList {    MLGB_t *head;    MLGB_t *tail;    int len;} LinkList_t;

链表的初始化:

/*   初始化链表   */void init_link_list(LinkList_t *nnd) {    nnd->head = NULL;    nnd->tail = NULL;    nnd->len = 0;    return;}

插入节点:

(一)、头部插入

  /*  成功返回 0   失败返回 -1   */int insert_node_head(MLGB_t *cnm, LinkList_t *nnd) {    if (cnm == NULL || nnd == NULL) {        perror("空链表..\n");        return -1;    }    if (nnd->head == NULL) {        // 当前链表为空        nnd->head = cnm;        nnd->tail = cnm;        cnm->next = NULL;        nnd->len = 1;        return 0;    } else {        // 当前链表不为空        cnm->next = nnd->head;        nnd->head = cnm;        nnd->len++;        return 0;    }    return 0;}

(二)、尾部插入

/*   尾部,节点插入   成功返回 0 ;失败返回 -1   */int insert_node_tail(MLGB_t *cnm, LinkList_t *nnd) {    if (cnm == NULL || nnd == NULL) {        perror("NULL 指针..\n");        return -1;    }    if (nnd->head == NULL) { // 链表为空        nnd->head = cnm;        nnd->tail = cnm;        cnm->next = NULL;        nnd->len = 1;        return 0;    } else {        nnd->tail->next = cnm;        nnd->tail = cnm;        cnm->next = NULL;        nnd->len++;        return 0;    }    return 0;}

链表的遍历:

/*   遍历链表   返回链表的长度   */int show_link_list(LinkList_t *nnd) {    if (nnd->len == 0) {        printf("空链表。。\n");    }    MLGB_t *temp = NULL;    temp = nnd->head;    while (temp != NULL) {        printf("编号(number): %d\t姓名(name): %s\t年龄(age): %d\n",                temp->monster.number, temp->monster.name, temp->monster.age);        temp = temp->next;    }    return nnd->len;}

销毁一个链表:

/*   销毁一个链表, 释放每个节点的内存,同时初始化链表为空   成功返回 0 ,失败返回 -1   */int destroy_linklist(LinkList_t *nnd) {    MLGB_t *current_p = NULL;    MLGB_t *temp_p = NULL;    current_p = nnd->head;    while (current_p != NULL) { // 删除当前节点        temp_p = current_p;        current_p = current_p->next;        free(temp_p);    }    init_link_list(nnd);    return 0;}

查找一个节点:

/*   通过编号(number)查找节点   成功返回节点的地址   失败返回 NULL   */MLGB_t * query_node_by_number(LinkList_t *nnd, int number1) {    MLGB_t *current_p = NULL;    current_p = nnd->head;    while (current_p != NULL) {        if (current_p->monster.number == number1) {            // 找到节点            return current_p;        }        current_p = current_p->next;    }    return NULL;}

删除一个节点:

/*   通过名字删除一个节点   成功返回 0   失败返回 -1 *node_point_del 用来保存被删除节点的地址 */int delete_by_name(LinkList_t *nnd, char *name1,        MLGB_t **node_point_del) {    MLGB_t *current_p = NULL; // 用来保存当前节点    MLGB_t *pre_p = NULL; // 用来保存前驱地址    current_p = nnd->head;    // 找节点    while (current_p != NULL) {        if (strcmp(current_p->monster.name, name1) == 0) {            if (current_p == nnd->head) {                // 要是删除的是头结点                nnd->head = nnd->head->next;                *node_point_del = current_p;            } else if (current_p == nnd->tail) {                // 如果是尾节点                nnd->tail = pre_p; // 指向前驱                pre_p = NULL;                *node_point_del = current_p;            } else {                pre_p->next = current_p->next;                *node_point_del = current_p;            }            nnd->len--;            return 0;        }        pre_p = current_p; // 记下 current_p 的前驱        current_p = current_p->next;    }    printf("没能找到 %s 的信息..\n", name1);    *node_point_del = NULL;    return -1;}

程序运行:

写个主程序测试一些功能,功能都实现了。

程序运行测试结果

0 0