当前位置: 首页 > news >正文

列表之链表_C

数据结构(邓俊辉):列表及相关概念_listnodeposi-CSDN博客

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

// 定义Rank类型为int
typedef int Rank;

// 定义ListNode结构体
typedef struct ListNode {
    int data;
    struct ListNode* pred;
    struct ListNode* succ;
} ListNode;

// 定义List结构体
typedef struct List {
    int _size;
    ListNode* header;
    ListNode* trailer;
} List;

// 链表初始化函数
void init(List* list) {
    list->header = (ListNode*)malloc(sizeof(ListNode));
    list->trailer = (ListNode*)malloc(sizeof(ListNode));
    list->header->succ = list->trailer;
    list->header->pred = NULL;
    list->trailer->pred = list->header;
    list->trailer->succ = NULL;
    list->_size = 0;
}

// 查找函数
ListNode* find(List* list, int e, int n, ListNode* p) {
    while (0 < n--) {
        if (e == (p = p->pred)->data) {
            return p;
        }
    }
    return NULL;
}

// 作为首节点插入函数
ListNode* insertAsFirst(List* list, int e) {
    list->_size++;
    return list->header->succ = list->header->insertAsSucc(e);
}

// 作为末节点插入函数
ListNode* insertAsLast(List* list, int e) {
    list->_size++;
    return list->trailer->pred = list->trailer->insertAsPred(e);
}

// 作为p的后继插入函数
ListNode* insertA(List* list, ListNode* p, int e) {
    list->_size++;
    return p->insertAsSucc(e);
}

// 作为p的前驱插入函数
ListNode* insertB(List* list, ListNode* p, int e) {
    list->_size++;
    return p->insertAsPred(e);
}

// 节点作为前驱插入函数
ListNode* insertAsPred(ListNode* p, int e) {
    ListNode* x = (ListNode*)malloc(sizeof(ListNode));
    x->data = e;
    x->pred = p->pred;
    x->succ = p;
    p->pred->succ = x;
    p->pred = x;
    return x;
}

// 节点作为后继插入函数
ListNode* insertAsSucc(ListNode* p, int e) {
    ListNode* x = (ListNode*)malloc(sizeof(ListNode));
    x->data = e;
    x->pred = p;
    x->succ = p->succ;
    p->succ->pred = x;
    p->succ = x;
    return x;
}

// 复制节点函数
void copyNOdes(List* list, ListNode* p, int n) {
    init(list);
    while (n--) {
        insertAsLast(list, p->data);
        p = p->succ;
    }
}

// 删除节点函数
int removeNode(List* list, ListNode* p) {
    int e = p->data;
    p->pred->succ = p->succ;
    p->succ->pred = p->pred;
    free(p);
    list->_size--;
    return e;
}

// 析构函数
void destroyList(List* list) {
    clear(list);
    free(list->header);
    free(list->trailer);
}

// 清除所有节点函数
int clear(List* list) {
    int oldSize = list->_size;
    while (0 < list->_size) {
        removeNode(list, list->header->succ);
    }
    return oldSize;
}

// 无序去重函数
int deduplicate(List* list) {
    if (list->_size < 2) {
        return 0;
    }
    int oldSize = list->_size;
    ListNode* p = list->header;
    Rank r = 0;
    while (list->trailer != (p = p->succ)) {
        ListNode* q = find(list, p->data, r, p);
        if (q) {
            removeNode(list, q);
        } else {
            r++;
        }
    }
    return oldSize - list->_size;
}

// 有序去重函数
int uniquify(List* list) {
    if (list->_size < 2) {
        return 0;
    }
    int oldSize = list->_size;
    ListNode* p = list->header->succ;
    ListNode* q;
    while (list->trailer != (q = p->succ)) {
        if (p->data != q->data) {
            p = q;
        } else {
            removeNode(list, q);
        }
    }
    return oldSize - list->_size;
}

// 遍历函数
void traverse(List* list, void (*visit)(int*)) {
    for (ListNode* p = list->header->succ; p != list->trailer; p = p->succ) {
        visit(&p->data);
    }
}

// 查找函数(有序区间查找)
ListNode* search(List* list, int e, int n, ListNode* p) {
    while (0 <= n--) {
        if (((p = p->pred)->data) <= e) {
            break;
        }
    }
    return p;
}

调试

// 测试函数
void printData(int* data) {
    printf("%d ", *data);
}

int main() {
    List list;
    init(&list);

    // 插入节点测试
    insertAsFirst(&list, 1);
    insertAsLast(&list, 3);
    insertA(&list, list.header->succ, 2);

    // 遍历测试
    traverse(&list, printData);
    printf("\n");

    // 查找测试
    ListNode* found = find(&list, 2, list._size, list.trailer);
    if (found) {
        printf("找到节点,值为:%d\n", found->data);
    } else {
        printf("未找到节点\n");
    }

    // 无序去重测试
    deduplicate(&list);
    traverse(&list, printData);
    printf("\n");

    // 有序去重测试
    insertAsLast(&list, 3);
    uniquify(&list);
    traverse(&list, printData);
    printf("\n");

    // 清除并销毁链表
    destroyList(&list);

    return 0;
}

在链表相关的数据结构中,“succ” 是 “successor” 的缩写,意思是 “后继者、继任者” 。在链表节点的定义中,将指针命名为 succ 就是用来指向当前节点的下一个节点,即后继节点。

这里的 pred 是 “predecessor” 的缩写,表示 “前驱者、前一个” ,pred 指针指向当前节点的前一个节点;

  • header:即头哨兵节点,它处于链表的起始位置,但并不存储实际的数据。其主要用途是作为链表第一个有效节点的前驱节点,便于对链表的操作。
  • trailer:也就是尾哨兵节点,它位于链表的末尾,同样不存储实际的数据。它的作用是作为链表最后一个有效节点的后继节点。

数据结构(邓俊辉):列表及相关概念_listnodeposi-CSDN博客

相关文章:

  • 三维空间中的离散曲线段匹配方法
  • 数据库学习
  • 程序化广告行业(73/89):买卖双方需求痛点及应对策略深度剖析
  • 通过可组合的数字体验平台(DXP)提升运营效率与个性化体验
  • echarts地图详解
  • spark课后总结
  • 【Java异步】解决@Async注解,同类下调用不生效
  • python自定义自己的类库
  • 基于django大数据平台的交通数据可视化设计与实现(源码+lw+部署文档+讲解),源码可白嫖!
  • pig 权限管理开源项目学习
  • 第 28 场 蓝桥入门赛 JAVA 完整题解
  • 训练数据清洗(文本/音频/视频)
  • 大数据 CDH 排除故障的步骤与技巧
  • AAAI 2025新研究!大语言模型+MARL=论文新思路?
  • CausalML 基于机器学习算法的因果推理方法
  • 基于Qt的串口通信工具
  • 【Pandas】pandas DataFrame copy
  • BLE 状态机设计思路
  • 清晰易懂的 Apollo 配置中心安装与使用教程
  • 巴特沃斯滤波器
  • q a wordpress插件下载/seo怎么弄
  • 做的比较好的美食网站有哪些/营业推广的目标通常是
  • 电子商务网站建设下载/公司网站设计制作
  • 百事通网做网站/医疗网站优化公司
  • 万户网络做网站如何/付费推广
  • 网站要注册为什么/运营推广的方式和渠道