数据结构 - (2)链表

链表整体代码及相关操作:

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

//声明结点结构
typedef struct ListNode {
    int data;
    struct ListNode *next;
} ListNode;


//声明链表结构
typedef struct LinkList {
    ListNode head;
    int length;
} LinkList;


//初始化结点
ListNode *init_listnode(int val) {
    ListNode *p = (ListNode *)malloc(sizeof(ListNode));
    p->data = val;
    p->next = NULL;
    return p;
}


//初始化链表
LinkList *init_linklist() {
    LinkList *l = (LinkList *)malloc(sizeof(LinkList));
    l->head.next = NULL;
    l->length = 0;
    return l;
}


//清除结点
void clear_listnode(ListNode *node) {
    if (node == NULL) return ;
    free(node);
    return ;
}


//清除链表
void clear_linklist(LinkList *l) {
    if (l == NULL) return ;
    ListNode *p = l->head.next, *q;
    while (p) {
        q = p->next;
        clear_listnode(p);
        p = q;
    }
    free(l);
    return ;
}


//数据(结点)插入
int insert(LinkList *l, int ind, int val) {
    if (l == NULL) return 0;
    if (ind < 0 || ind > l->length) return 0;
    ListNode *p = &(l->head), *node = init_listnode(val);
    while (ind--) {
        p = p->next;
    }
    node->next = p->next;
    p->next = node;
    l->length += 1;
    return 1;
}

//删除操作
int erase(LinkList *l, int ind) {
    if (l == NULL) return 0;
    if (ind < 0 || ind >= l->length) return 0;
    ListNode *p = &(l->head), *q;
    while (ind--) {
        p = p->next;
    }
    q = p->next->next;
    clear_listnode(p->next);
    p->next = q;
    l->length -= 1;
    return 1;
}

void output(LinkList *l) {
    printf("LinkList(%d) : ", l->length);
    //(for循环中跳出条件为当p为空,不为空则持续循环直到p为空)
    for (ListNode *p = l->head.next; p; p = p->next) {
        printf("%d -> ", p->data);
    }
    printf("NULL\n");
    return ;
}

//测试30次
#define MAX_OP 30

int main() {
    srand(time(0));
    LinkList *l = init_linklist();
    for (int i = 0; i < MAX_OP; i++) {
        int op = rand() % 3;    //随机数在0-2之间
        int ind = rand() % (l->length + 1); //插入位置0 到 lenght
        int val = rand() % 100;
        switch (op) {
            //0,1 都进行插入操作
            case 0:
            case 1: {
                printf("insert %d at %d to LinkList = %d\n", 
                       val, ind, insert(l, ind, val));
            } break;
            //2 进行删除操作
            case 2: {
                printf("erase item at %d from LinkList = %d\n", 
                      ind, erase(l, ind));
            } break;
        }
        output(l);
        printf("\n");
    }
    clear_linklist(l);
    return 0;
}

 

附:链表定义(发文)

    链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
    使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。
posted @ 2022-03-29 11:22  HanaKoo  阅读(66)  评论(0编辑  收藏  举报
@format