Bootstrap

C语言数据结构-----单链表

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

//本单链表是带头节点的

//为方便理解,本程序未进行公共代码提取成方法

//定义一个单链表
typedef struct Lnode {
    int data; //这个节点存储的数据
    struct Lnode *next; //自引用指针,这个节点的指针域,指向下一个节点
} Lnode;

//初始化单链表
Lnode *InitList() {
    Lnode *L = (Lnode *) malloc(sizeof(Lnode)); //为头指针分配一个内存空间
    //判断内存空间是否分配成功
    if (L == NULL) {
        return NULL;
    }
    L->next = NULL;
    return L;
}

//按位序插入元素,第i个位置插入第e个元素
bool ListInsert(Lnode *L, int i, int e) {
    //插入索引异常
    if (i < 1) {
        return false;
    }
    //p指向头指针
    Lnode *p = L;
    //用来计算当前p指向的是第几个节点
    int j = 0;
    //找到插入节点的前一个位置
    while (p != NULL && j < i - 1) {
        p = p->next;
        j++;
    }
    //i值超出单链表长度
    if (p == NULL) {
        return false;
    }
    //定义一个节点
    Lnode *s = (Lnode *) malloc(sizeof(Lnode));
    if (s == NULL) {
        return false;
    }
    //插入节点
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}

//指定节点的后插操作 在p节点后插入一个数据
bool InsertNextNode(Lnode *p, int e) {
    if (p == NULL) {
        return false;
    }
    //定义一个节点
    Lnode *l = (Lnode *) malloc(sizeof(Lnode));
    //判断内存是否分配成功
    if (l == NULL) {
        return false;
    }
    //插入节点
    l->data = e;
    l->next = p->next;
    p->next = l;
    return true;
}

//指定节点的前插操作
bool InsertBeforeNode(Lnode *p, int e) {
    //判断节点是否存在
    if (p == NULL) {
        return false;
    }
    Lnode *s = (Lnode *) malloc(sizeof(Lnode));
    //判断内存是否分配成功
    if (s == NULL) {
        return false;
    }
    //先在p节点后插入s节点,再把p节点的数据复制到s节点,
    //要插入的数据赋值于p节点,以实现前插操作
    s->next = p->next;
    p->next = s;
    s->data = p->data;
    p->data = e;
    return true;
}

//按位序删除元素,第i个位置删除元素,用e存储删除的元素
bool ListDelete(Lnode *L, int i, int *e) {
    //删除索引异常
    if (i < 1) {
        return false;
    }
    //p指向头指针
    Lnode *p = L;
    //用来计算当前p指向的是第几个节点
    int j = 0;
    //找到删除节点的前一个位置
    while (p != NULL && j < i - 1) {
        p = p->next;
        j++;
    }
    //i值超出单链表长度
    if (p == NULL) {
        return false;
    }
    //i节点已没有节点
    if (p->next == NULL) {
        return false;
    }
    //删除节点
    Lnode *s = p->next; //s为要删除的节点
    *e = s->data; //e存储删除节点的值
    //断开s节点
    p->next = s->next;
    s->next = NULL;
    //释放资源
    free(s);
    return true;
}

//指定节点的删除(不包含头结点和最后一个节点)
//头节点不能被删除,此处并未进行逻辑判断
//若p为最后一个节点,需找到前一个节点把其指针域赋值为NNll即可
bool DeleteNode(Lnode *p) {
    //节点不存在
    if (p == NULL) {
        return false;
    }

    Lnode *s = p->next; //s为删除节点的后一个节点
    p->data = s->data; //p节点数据域覆盖
    p->next = s->next; //p节点指针域覆盖
    free(s); //释放资源
    return true;
}

//按位查找
Lnode *GetElem(Lnode *l, int i) {
    //判断i是否合理
    if (i < 0) {
        return NULL;
    }
    //定义指针p指向头指针
    Lnode *p;
    p = l;
    //判断p指向的是第几个节点
    int j = 0;
    //找到第i个节点
    while (p != NULL && j < i) {
        p = p->next;
        j++;
    }
    return p;
}

//按值查找
Lnode *LocateElem(Lnode *l, int e) {
    //定义指针p指向头指针
    Lnode *p = l;
    //进行遍历查找
    while (p != NULL && p->data != e) {
        p = p->next;
    }
    //单链表没有该值
    if (p == NULL) {
        return NULL;
    }
    return p;
}

//尾插法建立单链表
Lnode *List_TailInsert() {
    //初始化单链表
    Lnode *p = InitList();
    //定义表尾指针
    Lnode *s = p;
    //插入的节点
    Lnode *prev;

    for (int i = 1; i <= 10; i++) {
        //为插入节点分配内存空间
        prev = (Lnode *) malloc(sizeof(Lnode));
        prev->data = i; //插入节点赋值
        s->next = prev; //连接链表
        s = prev; //表尾节点更换
    }
    //尾节点指针域为空
    s->next = NULL;
    return p;
}

//头插法建立单链表
Lnode *List_HeadInsert() {
    //初始化单链表
    Lnode *p = InitList();
    //插入的节点
    Lnode *prev;
    for (int i = 1; i <= 10; i++) {
        //为插入节点分配内存空间
        prev = (Lnode *) malloc(sizeof(Lnode));
        prev->data = i; //插入节点赋值
        prev->next = p->next; //插入节点指针域赋值
        p->next = prev; //头结点和插入指针建立关系
    }
    return p;
}

//测试
void main(void) {
    //尾插法建立单链表
    printf("尾插法\n");
    Lnode *p = List_TailInsert();
    //测试数据用的节点
    Lnode *p1 = p;
    Lnode *p2 = p;
    Lnode *p3 = p;
    Lnode *p4 = p;

    for (int i = 0; i < 10; i++) {
        p = p->next;
        printf("%d\t", p->data);
    }
    printf("\n");
    //查找
    Lnode *s1 = GetElem(p1, 2);
    printf("%d\n", s1->data);

    Lnode *s2 = LocateElem(p2, 8);
    printf("%d\n", s2->data);

    //增加
    ListInsert(p3, 3, 2);
    for (int i = 0; i < 11; i++) {
        p3 = p3->next;
        printf("%d\t", p3->data);
    }
    printf("\n");
    //重置为第二个节点;
    p3 = p4->next->next;
    InsertNextNode(p3, 10);
    //重置为指向头节点的指针
    p3 = p4;
    for (int i = 0; i < 12; i++) {
        p3 = p3->next;
        printf("%d\t", p3->data);
    }
    //删除操作同增加
    printf("\n头插法\n");
    Lnode *h = List_HeadInsert();
    for (int i = 0; i < 10; i++) {
        h = h->next;
        printf("%d\t", h->data);
    }
}

;