C语言链表操作

  • 项目名称
    Link_List

  • 文件

head.h

#ifndef LINK_LIST_HEAD_H
#define LINK_LIST_HEAD_H

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

typedef enum _gender_ {man, women} Gender; // 性别

typedef struct std {
    int          ID;       // ID
    char         name[21]; // 姓名
    Gender       gender;   // 性别
    int          age;      // 年龄
    struct std*  next;     // 下一个节点
} Std;

Std* Link_created(void); // 创造链表
bool Link_input(Std* index_Std); // 输入链表中一个节点的内容
bool Link_output(Std* index_Std); // 输出链表中一个节点的内容
bool Link_input_check(void); // 检查是否继续输入(用于构建和添加)
bool Link_malloc(Std** p, int len); // 向p指针内分配len个节点的内存
Std* Link_search(Std* head, int index_ID); // 根据ID查找节点 若找不到则返回NULL(ID必须唯一)
Std* Link_before(Std* head, int index_ID); // 返回前一节点 若没有则返回NULL
Std* Link_after(Std* head, int index_ID); // 返回后一节点 若没有则返回NULL
bool Link_insert_ID_bef(Std** head, int index_ID); // 在对应ID的节点的前面插入节点
bool Link_insert_ID_aft(Std* head, int index_ID); // 在对应ID的节点的后面插入节点
bool Link_insert_Std_bef(Std** head, Std* index_Std); // 在对应节点的前面插入节点
bool Link_insert_Std_aft(Std* head, Std* index_Std); // 在对应节点的后面插入节点
bool Link_delete_ID(Std** head, int index_ID); // 删除对应ID的节点
bool Link_delete_name(Std** head, char* index_name); // 删除所有具有对应姓名的节点
bool Link_delete_gender(Std** head, Gender index_gender); // 删除所有具有对应性别的节点
bool Link_delete_age(Std** head, int index_age); // 删除所有具有对应年龄的节点
bool Link_delete_Std(Std** head, Std* index_Std); // 删除对应节点
bool Link_free(Std* head); // 释放整个链表的内存
bool Link_add_head(Std** head); // 在链表的头部添加一系列节点
bool Link_add_end(Std* end); // 在链表的尾部添加一系列节点
bool Link_display(Std* head); // 打印链表内容
bool Link_display_name(Std* head); // 打印链表内所有的姓名
bool Link_reversal(Std** head); // 反转链表
int Link_get_ID(Std* index_Std); // 获得节点的ID
char* Link_get_name(Std* index_Std); // 获得节点的姓名
Gender Link_get_gender(Std* index_Std); // 获得节点的性别
int Link_get_age(Std* index_Std); // 获得节点的年龄
bool Link_next(Std** index_Std); // 指向下一个节点
bool Link_arrange_ID(Std* head); // 根据ID排序
bool Link_linked(Std* head, Std* end); // 连接节点
bool Link_swap(Std* a, Std* b); // 交换节点的内容
bool Link_copy_all(Std* dest, Std* src); // 复制节点的所有内容(包含next)
bool Link_copy_value(Std* dest, Std* src); // 复制节点的内容(不包含next)

#endif //LINK_LIST_HEAD_H


main.c

#include "head.h"

int main()
{
#if false
    /* test1 */ {
        Std* test = Link_created();
        printf("\n\nNow input another.\n\n");
        Std* det = Link_created();

        Link_display(test);
        printf("Display end.\n\n");

        while (det != NULL) {
            Link_delete_age(&test, Link_get_age(det));
            det = det->next;
        }

        Link_display(test);
        printf("Display end.\n\n");

        Link_free(test);
    } // 此处测试可演示作业2
    /**
     * 建立一个链表
     * 每个节点包括:学号,姓名,性别以及年龄
     * 输入一个链表
     * 如果链表中的节点所包含的年龄等于此年龄,则将此节点删去
     */
    /**
     * 1.  Created
     * 2.  Malloc
     * 3.  Input
     * 4.  Input Check
     * 5.  Next
     * 6.  Display
     * 7.  Output
     * 8.  Free
     * 9.  Get Age
     * 10. Delete Age
     */
#endif

#if false
    /* test2 */ {
        Std* test = Link_created();

        Link_display(test);
        printf("Display end.\n\n");

        Link_reversal(&test);
        Link_display(test);
        printf("Reversal end.\n\n");

        Link_free(test);
    } // 此处测试可演示作业3
    /**
     * 通过指针将单链表直接倒序
     * (不声明新链表或者数组)
     * (这个题搞懂了,链表这块就没什么大问题了)
     */
    /**
     * 1. Reversal
     */
#endif

#if false
    /* test3 */ {
        Std* test = Link_created();

        Link_display(test);
        printf("Display end.\n\n");

        Std* ret = Link_search(test, 2);
        Link_output(ret);
        printf("Search end.\n\n");

        Std* before = Link_before(test, ret->ID);
        Link_output(before);
        printf("Before end.\n\n");

        Std* after = Link_after(test, ret->ID);
        Link_output(after);
        printf("After end.\n\n");

        Link_arrange_ID(test);
        Link_display(test);
        printf("Arrange end.\n\n");

        Link_free(test);
    }
    /**
     * 1. Search
     * 2. Before
     * 3. After
     * 4. Arrange
     * 5. Copy
     * 6. Swap
     */
#endif

#if false
    /* test4 */ {
        Std* test = Link_created();

        Link_display(test);
        printf("Display end.\n\n");

        Link_delete_ID(&test, 2);
        Link_display(test);
        printf("Delete_ID end.\n\n");

        Link_display_name(test);
        char name[21];
        scanf("%s", name);
        Link_delete_name(&test, name);
        Link_display(test);
        printf("Delete_name end.\n\n");

        Link_delete_gender(&test, 0);
        Link_display(test);
        printf("Delete_gender end.\n\n");

        Link_delete_age(&test, 18);
        Link_display(test);
        printf("Delete_age end.\n\n");

        Link_free(test);
    }
    /**
     * 1. Delete
     * 2. Display Name
     */
#endif

#if false
    /* test5 */ {
        Std* test = NULL;
        Link_malloc(&test, 1);
        Link_input(test);

        printf("----------------\n");
        printf("ID:     %d\n", Link_get_ID(test));
        printf("name:   %s\n", Link_get_name(test));
        if (Link_get_gender(test) == man) {
            printf("gender: man\n");
        }
        else {
            printf("gender: women\n");
        }
        printf("age:    %d\n", Link_get_age(test));
        printf("----------------\n");Link_display(test);

        printf("Get end.\n\n");

        Link_free(test);
    }
    /**
     * 1. Get
     */
#endif

#if false
    /* test6 */ {
        Std* test = Link_created();

        Link_display(test);
        printf("Display end.\n\n");

        Link_insert_ID_aft(test, 1);
        Link_display(test);
        printf("Insert_aft end.\n\n");

        Link_insert_ID_bef(&test, 1);
        Link_display(test);
        printf("Insert_bef end.\n\n");

        Std* ID_2 = Link_search(test, 2);

        Link_insert_Std_aft(test, ID_2);
        Link_display(test);
        printf("Insert_aft end.\n\n");

        Link_insert_Std_bef(&test, ID_2);
        Link_display(test);
        printf("Insert_bef end.\n\n");

        Link_add_head(&test);
        Link_display(test);
        printf("Add_head end.\n\n");

        while (test->next) {
            test = test->next;
        }
        Link_add_end(test);
        Link_display(test);
        printf("Add_end end.\n\n");

        Link_free(test);
    }
    /**
     * 1. Insert
     * 2. Add
     */
#endif

#if false
    /* test7 */ {
        Std* test1 = NULL;
        Link_malloc(&test1, 1);
        Link_input(test1);

        Std* test2 = NULL;
        Link_malloc(&test2, 1);
        Link_input(test2);

        Std* test3 = NULL;
        Link_malloc(&test3, 1);
        Link_input(test2);

        Std* test4 = NULL;
        Link_malloc(&test4, 1);

        Link_linked(test1, test2);
        Link_linked(test2, test3);

        Link_copy_all(test4, test2);
        Link_linked(test1, test4);
        free(test2);

        Link_display(test1);
        printf("Display end.\n\n");

        Link_free(test1);
    }
    /**
     * 1. Linked
     * 2. Copy All
     */
#endif
    return 0;
}

Link_add.c

#include "head.h"

bool Link_add_head(Std** head)
{
    if (*head == NULL) {
        return false;
    } // 若为空链表则返回
    do {
        Std *new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建新的节点
        new->next = *head; // 链接
        *head = new; // 改变头指针
    } while (Link_input_check()); // 按照输入判断是否继续添加
    return true;
}

bool Link_add_end(Std* end)
{
    if (end == NULL) {
        return false;
    } // 若为空链表则返回
    do {
        Std *new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建新的节点
        end->next = new; // 链接
        end = new; // 改变尾指针
    } while (Link_input_check()); // 按照输入判断是否继续添加
    return true;
}

Link_after.c

#include "head.h"

Std* Link_after(Std* head, int index_ID)
{
    if (head == NULL) {
        return NULL;
    } // 若为空链表则返回false
    while (head != NULL) {
        if (head->ID == index_ID) {
            return head->next; // 找到则返回该节点
        }
        head = head->next;
    } // 遍历链表
    return NULL; // 找不到则返回NULL
}

Link_arrange.c

#include "head.h"

bool Link_arrange_ID(Std* head)
{
    if (head == NULL) {
        return true;
    }
    Std* i = head;
    while (i->next != NULL) {
        Std* j = i;
        int min_ID = j->ID;
        Std* min = j;
        while (j->next != NULL) {
            if (j->next->ID < min_ID) {
                min_ID = j->next->ID;
                min = j->next;
            }
            j = j->next;
        }
        Link_swap(i, min);
        i = i->next;
    } // 选择排序
    return true;
}

Link_before.c

#include "head.h"

Std* Link_before(Std* head, int index_ID)
{
    if (head == NULL) {
        return NULL;
    } // 若为空链表则返回false
    if (head->ID == index_ID) {
        return NULL;
    } // 若该节点为头节点则返回NULL
    while (head->next != NULL) {
        if (head->next->ID == index_ID) {
            return head; // 找到则返回该节点
        }
        head = head->next;
    } // 遍历链表
    return NULL; // 找不到则返回NULL
}

Link_copy.c

#include "head.h"

bool Link_copy_all(Std* dest, Std* src)
{
    if (dest == NULL || src == NULL) {
        return false;
    }
    dest->ID = src->ID;
    strcpy(dest->name, src->name);
    dest->gender = src->gender;
    dest->age = src->age;
    dest->next = src->next;
    return true;
}

bool Link_copy_value(Std* dest, Std* src)
{
    if (dest == NULL || src == NULL) {
        return false;
    }
    dest->ID = src->ID;
    strcpy(dest->name, src->name);
    dest->gender = src->gender;
    dest->age = src->age;
    return true;
}

Link_created.c

#include "head.h"

Std* Link_created(void)
{
    Std* head = NULL;
    Std* p = NULL;
    Link_malloc(&p, 1);
    Link_input(p); // 先创建头节点
    head = p;
    while (Link_input_check()) {
        Link_malloc(&(p->next), 1);
        Link_next(&p);
        Link_input(p);
    } // 根据输入判断是否继续输入

    return head; // 返回头指针
}

Link_delete.c

#include "head.h"

bool Link_delete_ID(Std** head, int index_ID)
{
    if (*head == NULL) {
        return false;
    } // 若为空链表,返回false
    Std* det = Link_search(*head, index_ID); // 查找对应节点
    if (det == NULL) {
        return false;
    } // 若找不到,返回false
    if ( Link_delete_Std(&(*head), det) ) {
        return true;
    } // 删除成功返回true
    else {
        return false;
    } // 删除失败返回false
}

bool Link_delete_name(Std** head, char* index_name)
{
    if (*head == NULL) {
        return false;
    } // 若为空链表,返回false
    Std* p = *head;
    while (p) { // 遍历链表
        if (strcmp(p->name, index_name) == 0) {
            Link_delete_Std(&(*head), p); // 若相同则删除对应节点
        }
        p = p->next;
    }
    return true;
}

bool Link_delete_gender(Std** head, Gender index_gender)
{
    if (*head == NULL) {
        return false;
    } // 若为空链表,返回false
    Std* p = *head;
    while (p) { // 遍历链表
        if (p->gender == index_gender) {
            Link_delete_Std(&(*head), p); // 若相同则删除对应节点
        }
        p = p->next;
    }
    return true;
}

bool Link_delete_age(Std** head, int index_age)
{
    if (*head == NULL) {
        return false;
    } // 若为空链表,返回false
    Std* p = *head;
    while (p) { // 遍历链表
        if (p->age == index_age) {
            Link_delete_Std(&(*head), p); // 若相同则删除对应节点
        }
        p = p->next;
    }
    return true;
}

bool Link_delete_Std(Std** head, Std* index_Std)
{
    if (*head == NULL) {
        return false;
    } // 若为空链表,返回false
    Std* before = Link_before(*head, index_Std->ID); // 找到链表的前一个节点(前一个节点存在则节点一定存在)
    if (before == NULL) { // 前一个节点为空时
        if ((*head)->ID == index_Std->ID) { // 判断节点是否为头节点
            Std* temp = *head;
            *head = (*head)->next;
            free(temp);
            return true; // 删除头节点
        }
        else {
            return false; // 若不是头节点则返回false(链表中不存在这个节点)
        }
    }
    Std* after = index_Std->next; // 找到链表的后一个节点(此时节点一定存在)
    if (after == NULL) { // 后一个节点为空时(即节点为尾节点)
        before->next = NULL;
        free(index_Std);
        return true; // 删除尾节点
    }
    else {
        before->next = after;
        free(index_Std);
        return true; // 删除中间节点
    }
}

Link_display.c

#include "head.h"

bool Link_display(Std* head)
{
    if (head == NULL) {
        return false;
    } // 若为空链表则返回
    while ( head != NULL ) {
        Link_output(head);
        head = head->next;
    }
    return true;
}

bool Link_display_name(Std* head)
{
    if (head == NULL) {
        return false;
    } // 若为空链表则返回
    printf("----------------\n");
    while (head != NULL) {
        printf("%s\n", head->name);
        head = head->next;
    }
    printf("----------------\n");
    return true;
}

Link_free.c

#include "head.h"

bool Link_free(Std* head)
{
    if (head == NULL) {
        return false;
    } // 若为空链表则返回false
    Std* temp = NULL; // 用于保存节点
    while (head->next) {
        temp = head;
        head = head->next;
        free(temp);
    } // 遍历链表
    free(head);
    return true;
}

Link_get.c

#include "head.h"

int Link_get_ID(Std* index_Std)
{
    return index_Std->ID;
}

char* Link_get_name(Std* index_Std)
{
    return index_Std->name;
}

Gender Link_get_gender(Std* index_Std)
{
    return index_Std->gender;
}

int Link_get_age(Std* index_Std)
{
    return index_Std->age;
}

Link_input.c

#include "head.h"

bool Link_input(Std* index_Std)
{
    if (index_Std == NULL) {
        return false;
    }
    printf("Waiting for your input.\n");
    printf("0 means man and 1 means women.\n");
    printf("----------------\n");

    printf("ID:     ");
    scanf("%d", &(index_Std->ID));

    printf("name:   ");
    scanf("%20s", index_Std->name);

    printf("gender: ");
    int gender;
    scanf("%d", &gender);
    if (gender) {
        index_Std->gender = women;
    } else {
        index_Std->gender = man;
    }

    printf("age:    ");
    scanf("%d", &(index_Std->age));

    index_Std->next = NULL;

    printf("----------------\n");

    return true;
}

bool Link_input_check(void)
{
    getchar();// For get the '\n'
    printf("Continue to input?\n\"q\" to quit and \"c\" to continue.\n");
    char check;
    scanf("%c", &check);
    return (check == 'q')?false:true;
}

Link_insert.c

#include "head.h"

bool Link_insert_ID_bef(Std** head, int index_ID)
{
    if (head == NULL) {
        return false;
    } // 若为空链表,返回false
    Std* before = Link_before(*head, index_ID); // 找到链表的前一个节点(前一个节点存在则节点一定存在)
    if (before == NULL) { // 前一个节点为空时
        if ((*head)->ID == index_ID) { // 判断节点是否为头节点
            Std* new = NULL;
            Link_malloc(&new, 1);
            Link_input(new); // 创建新的节点
            new->next = *head;
            *head = new; // 链接
            return true;
        }
        else {
            return false;
        }
    }
    else { // 找到了前一个节点
        Std* p = before->next; // 后一个节点(即传入的节点)
        Std* new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建节点
        before->next = new;
        new->next = p; // 链接
        return true;
    }
}

bool Link_insert_ID_aft(Std* head, int index_ID)
{
    if (head == NULL) {
        return false;
    } // 若为空链表,返回false
    Std* p = Link_search(head, index_ID); // 查找对应节点
    if (p == NULL) {
        return false;
    } // 若找不到则返回false
    Std* after = p->next; // 下一个节点
    if (after == NULL) { // 没有下一个节点则节点为尾节点
        Std *new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建新的节点
        p->next = new; // 链接
        return true;
    }
    else { // 有下一个节点则为中间的节点
        Std *new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建新的节点
        p->next = new;
        new->next = after; // 链接
        return true;
    }
}

bool Link_insert_Std_bef(Std** head, Std* index_Std)
{
    if (head == NULL || index_Std == NULL) {
        return false;
    } // 若为空链表或空节点则返回false
    Std* before = Link_before(*head, index_Std->ID); // 前一个节点
    if (before == NULL) { // 前一节点为空时
        if (index_Std->ID == (*head)->ID) { // 判断是否为头节点
            Std *new = NULL;
            Link_malloc(&new, 1);
            Link_input(new); // 创建新的节点
            new->next = *head; // 链接
            *head = new; // 改变头指针
            return true;
        }
        else {
            return false; // 不是头节点则返回false(该节点不存在)
        }
    }
    else { // 前一节点不为空时
        Std *new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建新的节点
        before->next = new;
        new->next = index_Std; // 链接
        return true;
    }
}

bool Link_insert_Std_aft(Std* head, Std* index_Std)
{
    if (head == NULL || index_Std == NULL) {
        return false;
    } // 若为空链表或空节点则返回false
    Std* p = Link_search(head, index_Std->ID); // 查找对应节点
    if (p == NULL) {
        return false;
    } // 若找不到则返回false
    Std* after = index_Std->next; // 后一个节点
    if (after == NULL) { // 若后一个节点为空则为尾节点
        Std *new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建新节点
        index_Std->next = new; // 链接
        return true;
    }
    else { // 若后一个节点不为空则为中间节点
        Std *new = NULL;
        Link_malloc(&new, 1);
        Link_input(new); // 创建新节点
        index_Std->next = new;
        new->next = after; // 链接
        return true;
    }
}

Link_linked.c

#include "head.h"

bool Link_linked(Std* head, Std* end)
{
    if (head == NULL || end == NULL) {
        return false;
    }
    head->next = end;
    return true;
}

Link_malloc.c

#include "head.h"

bool Link_malloc(Std** p, int len)
{
    if (p == NULL) {
        return false;
    }
    *p = (Std*)malloc(len * sizeof(Std));
    if (*p == NULL) {
        return false;
    }
    else {
        return true;
    }
}

Link_next.c

#include "head.h"

bool Link_next(Std** index_Std)
{
    if (*index_Std == NULL) {
        return false;
    }
    *index_Std = (*index_Std)->next;
    return true;
}

Link_output.c

#include "head.h"

bool Link_output(Std* index_Std)
{
    if (index_Std == NULL) {
        return false;
    }
    printf("----------------\n");
    printf("ID:     %d\n", index_Std->ID);
    printf("name:   %s\n", index_Std->name);
    if (index_Std->gender == man) {
        printf("gender: man\n");
    }
    else {
        printf("gender: women\n");
    }
    printf("age:    %d\n", index_Std->age);
    printf("----------------\n");
    return true;
}

Link_reversal.c

#include "head.h"

bool Link_reversal(Std** head)
{
    if (*head == NULL|| (*head)->next == NULL) {
        return false;
    } // 若为空链表或只有一个节点的链表则返回false(不能反转)
    Std* p = NULL;
    Std* q = NULL;
    Std* r = NULL; // 用于反转的指针
    p = *head;
    q = p->next;
    p->next = NULL; // 头变尾
    while ( q != NULL ) { // 当到末尾时结束循环
        r = q->next;
        q->next = p;
        p = q;
        q = r;
    } // 将后一个节点拆下来链接到前一个节点上
    *head = p; // 改变头节点
    return true;
}

Linkl_search.c

#include "head.h"

Std* Link_search(Std* head, int index_ID)
{
    if (head == NULL) {
        return NULL;
    } // 如果链表为空则返回false
    while (head != NULL) { // 遍历链表
        if (head->ID == index_ID) {
            return head;
        } // 若找到则返回节点
        head = head->next; // 遍历
    }
    return NULL; // 遍历结束(找不到)返回false
}

Link_swap.c

#include "head.h"

bool Link_swap(Std* a, Std* b)
{
    if (a == NULL || b == NULL) {
        return false;
    }
    Std* temp = NULL; // 创建临时节点
    temp = (Std*)malloc(sizeof(Std)); // 分配内存
    Link_copy_value(temp, a);
    Link_copy_value(a, b);
    Link_copy_value(b, temp); // 交换内容
    free(temp); // 释放临时节点的内存
    return true;
}
发布了7 篇原创文章 · 获赞 5 · 访问量 1456

猜你喜欢

转载自blog.csdn.net/AimerNeige/article/details/102985504
今日推荐