【数据结构与算法】【知识体系整理】2-链表

【数据结构与算法】【知识体系整理】2-链表

1 链表

为了更好地理解链表,我们和顺序表对比。顺序表需要一段连续的存储空间,且初始化时就固定了长度。如果后续发现空间不够用,则需要扩容。

链表的每个节点都是“数据+指针”的格式,通过指针将各元素连接起来,因此不需要连续的存储空间。链表的长度不固定,也不需要扩容。

头指针指向链表中第一个节点的地址。最后一个节点的指针为NULL。

在这里插入图片描述

链表的结构定义:data、next指针。

单向链表的操作

插入

如想将节点new插入到链表中第n个位置,首先从链表头部向后遍历,找到第n-1个节点。使节点new指向第n个节点,然后再使得节点n-1指向节点new即可。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

删除

如想删除节点n,首先从链表头部向后遍历,找到第n-1个节点。为了避免内存泄露,要先定义一个临时指针,指向待删除节点。然后让节点n-1的后继指针指向节点n+1。

单向循环链表

单向循环链表的尾节点的后继指针指向头节点,形成一个环路。head指向整个单向循环链表的尾节点(考虑到插入到index为0的位置)。在插入、删除等操作中,要注意保持head指向单向循环列表的尾结点。

在这里插入图片描述

在这里插入图片描述

leetcode练习:19、24、83、141、160、202、203、206、234、237。

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

typedef struct Node {
    int data;
    struct Node *next;
} Node;

typedef struct List {
    Node head;
    int size;
} List;

Node *node_create(int val)
{
    Node *node = (Node *)malloc(sizeof(Node));
    if (node == NULL) return NULL;

    node->data = val;
    node->next = NULL;
    return node;
}

void node_destroy(Node *node)
{
    if (node == NULL) return;
    free(node);
    return;
}

List *list_create()
{
    List *list = (List *)malloc(sizeof(List));
    if (list == NULL) return NULL;
    list->head.next = NULL;
    list->size = 0;
    return list;
}

void list_destroy(List *list)
{
    if (list == NULL) return;
    Node *p = list->head.next;
    while (p != NULL) {
        list->head.next = p->next;
        free(p);
        p = list->head.next;
    }
    free(list);
    return;
}

int list_insert(List *list, int idx, int val)
{
    if (list == NULL) return -1;
    if (idx < 0 || idx > list->size) return -1;
    Node *new_node = node_create(val);
    if (new_node == NULL) return -1;

    Node *p = &(list->head);
    while (idx--) {
        p = p->next;
    }
    new_node->next = p->next;
    p->next = new_node;
    list->size++;
    return 0;
}

int list_erase(List *list, int idx)
{
    if (list == NULL) return -1;
    if (idx < 0 || idx > list->size - 1) return -1;

    Node *p = &(list->head);
    Node *q = NULL;
    while (idx--) {
        p = p->next;
    }
    q = p->next;
    p->next = q->next;
    node_destroy(q);
    list->size--;
    return 0;
}

void list_reverse(List *list)
{
    if (list == NULL) return;
    Node *p = list->head.next;
    Node *q = NULL;
    list->head.next = NULL;

    while (p != NULL) {
        q = p->next;
        p->next = list->head.next;
        list->head.next = p;
        p = q;
    }
    return;
}

void list_output(List *list)
{
    if (list == NULL) return;
    Node *p = list->head.next;
    printf("List: HEAD->");
    while (p != NULL) {
        printf("%d->", p->data);
        p = p->next;
    }
    printf("NULL\n");
    return;
}

int main()
{
    srand(time(0));
    #define MAX_OP 20
    List *l = list_create();
    for (int i = 0; i < MAX_OP; i++)
    {
        int op = rand() % 4;
        int val = rand() % 100;
        int ind = rand() % (l->size + 3) -1;
        switch (op)
        {
            case 0:
            case 1:
                printf("Insert %d at %d to list = %d\n", val, ind, list_insert(l, ind, val));
                break;
            case 2:
                printf("Reverse the List!\n");
                list_reverse(l);
                break;
            case 3:
                printf("Erase the item at %d from list = %d\n", ind, list_erase(l, ind));
                break;
            default:
                break;
        }
        list_output(l);
        printf("\n");
    }
    #undef MAX_OP
    list_destroy(l);
    return 0;
}

单项循环链表、双向链表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值