首页 > 其他分享 >12月16日总结

12月16日总结

时间:2025-01-10 18:46:22浏览次数:1  
标签:总结 head 12 DoubleListNode 16 next current NULL 节点

今日学习了双链表的相关操作:
一、创建双链表
创建双链表的第一步是定义节点结构体,它包含数据域、指向前驱节点的指针 prev 和指向后继节点的指针 next。
// 双链表节点结构体定义
typedef struct DoubleListNode {
int data;
struct DoubleListNode *prev;
struct DoubleListNode *next;
} DoubleListNode;

初始化时,将表头指针设为 NULL,此时链表为空。当要逐个添加节点构建链表时,以尾插法为例:
DoubleListNode* createDoubleLinkedList() {
DoubleListNode *head = NULL;
DoubleListNode *tail = NULL;
int value;
scanf("%d", &value); // 输入节点数据,以特定值(如 -1)结束输入
while (value!= -1) {
DoubleListNode *newNode = (DoubleListNode *)malloc(sizeof(DoubleListNode));
newNode->data = value;
newNode->prev = NULL;
newNode->next = NULL;
if (head == NULL) {
head = newNode;
tail = newNode;
} else {
tail->next = newNode;
newNode->prev = tail;
tail = newNode;
}
scanf("%d", &value);
}
return head;
}

上述代码在添加节点过程中,对于非空链表,新节点的前驱指针指向当前尾节点,尾节点的后继指针指向新节点,然后更新尾节点为新节点,确保链表正确构建。
二、插入节点
头插法:
void insertAtHead(DoubleListNode **head, int value) {
DoubleListNode *newNode = (DoubleListNode )malloc(sizeof(DoubleListNode));
newNode->data = value;
newNode->next = head;
newNode->prev = NULL;
if (
head!= NULL) {
(
head)->prev = newNode;
}
*head = newNode;
}

先创建新节点,让其后继指向原表头,前驱置空,若原表头非空,原表头前驱指向新节点,最后更新表头指针。
中间插入:假设要在值为 target 的节点后插入新节点。
void insertAfter(DoubleListNode *head, int target, int value) {
DoubleListNode *current = head;
while (current!= NULL && current->data!= target) {
current = current->next;
}
if (current == NULL) {
return; // 未找到目标节点,插入失败
}
DoubleListNode *newNode = (DoubleListNode *)malloc(sizeof(DoubleListNode));
newNode->data = value;
newNode->prev = current;
newNode->next = current->next;
if (current->next!= NULL) {
current->next->prev = newNode;
}
current->next = newNode;
}

先定位目标节点,新节点前驱、后继指针相应连接,若目标节点后有节点,其后继节点前驱指针也需更新。
尾插法:类似创建链表尾插过程,找到尾节点插入即可。
三、删除节点
删除表头节点:
void deleteAtHead(DoubleListNode **head) {
if (*head == NULL) {
return; // 空链表,无需删除
}
DoubleListNode temp = head;
head = (head)->next;
if (
head!= NULL) {
(
head)->prev = NULL;
}
free(temp);
}

保存表头指针,更新表头,若新表头非空,其前驱置空,释放原表头内存。
删除中间节点:要删除值为 key 的节点。
void deleteNode(DoubleListNode **head, int key) {
if (*head == NULL) {
return; // 空链表
}
DoubleListNode *current = *head;
while (current!= NULL && current->data!= key) {
current = current->next;
}
if (current == NULL) {
return; // 未找到要删除的节点
}
if (current->prev!= NULL) {
current->prev->next = current->next;
} else {
*head = current->next;
}
if (current->next!= NULL) {
current->next->prev = current->prev;
}
free(current);
}

先定位节点,若有前驱、后继,分别调整指针跳过该节点,再释放其内存。
四、遍历双链表
正向遍历:
void printForward(DoubleListNode *head) {
DoubleListNode *current = head;
while (current!= NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}

从表头顺着后继指针逐个访问节点输出数据。
反向遍历:
void printBackward(DoubleListNode *head) {
DoubleListNode *tail = head;
while (tail->next!= NULL) {
tail = tail->next;
}
while (tail!= NULL) {
printf("%d ", tail->data);
tail = tail->prev;
}
printf("\n");
}

先找到尾节点,再依着前驱指针回溯输出数据。
这些双链表操作相互配合,为解决复杂的数据处理问题提供了有力手段,熟练掌握它们是运用双链表的关键。

标签:总结,head,12,DoubleListNode,16,next,current,NULL,节点
From: https://www.cnblogs.com/Genghao11/p/18664505

相关文章

  • 12月17日总结
    今日重点学习数据结构中的栈,它遵循后进先出原则,类似单端进出的储物箱,顶部是唯一的数据出入口,这使其在处理特定顺序问题上优势显著。学习中探究了栈的基本操作,初始化时用结构体表示栈,含存储数据的数组(或链表)与指示栈顶的指针top,初始top设为-1代表空栈。入栈是先让top加1......
  • 12月22日
    今日深入学习了Java中的注解(Annotations)机制,这是Java语言的一个重要特性,用于为程序元素(如类、方法、字段等)提供元数据。注解不直接影响程序的直接运行,但可以被编译器、工具或运行时环境读取和处理,从而实现各种强大的功能,如代码生成、依赖注入、测试等。注解是Java语言中的一种特......
  • 12月18日总结
    今日学习了栈的相关操作:初始化:defineMAX_SIZE100//假设栈的最大容量为100typedefstructStack{intdata[MAX_SIZE];inttop;}Stack;//栈的初始化函数voidinitStack(Stack*s){s->top=-1;}一、增-入栈(Push)入栈操作是向栈顶添加一个新元素,使其成为新的......
  • 12月19日总结
    今日深入学习了数据结构中的队列,它与之前所学的栈有着截然不同的特性。概念上,队列遵循先进先出(FIFO)原则,就如同日常生活中的排队场景,先到的人先接受服务,最先进入队列的元素最先被取出。它有队头(front)和队尾(rear)两个关键指针,分别用于标识队列的起始位置和末尾位置,元素从队尾进入,从......
  • 12月24日
    学习内容概述今日深入学习了Java中的泛型(Generics)机制,这是Java语言的一个重要特性,用于在编译时提供类型安全的集合和方法。泛型可以提高代码的复用性、可读性和安全性,是现代Java编程中不可或缺的一部分。泛型的基本概念泛型是一种在编译时提供类型检查的机制,允许在定义类、接口......
  • 12月15日
    今日重点学习了Java中的多线程编程,这是现代编程中实现并发和提高程序性能的关键技术。多线程可以让程序同时执行多个任务,充分利用计算机的多核处理器资源,提升程序的执行效率和响应速度。线程是程序执行的最小单位,是操作系统能够进行调度的最小单位。一个进程可以包含多个线程,这些......
  • P4069 [SDOI2016] 游戏
    P4069[SDOI2016]游戏题目描述Alice和Bob在玩一个游戏。游戏在一棵有\(n\)个点的树上进行。最初,每个点上都只有一个数字,那个数字是\(123456789123456789\)。有时,Alice会选择一条从\(s\)到\(t\)的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点......
  • 12月16日
    在多线程环境中,多个线程可能会同时访问和修改共享资源,这可能导致数据不一致和竞态条件等问题。为了保证数据的正确性和一致性,需要对线程进行同步和互斥控制。同步代码块:通过在代码块前加上synchronized关键字,可以将代码块标记为同步代码块。同步代码块需要指定一个锁对象,当线程进......
  • 12月12日总结
    今日复习了线性表中顺序表的相关操作初始化:voidInitList(SqList&L){ //申请存储空间 L.data=(int*)malloc(InitSize*sizeof(int)); L.length=0; L.MaxSize=InitSize;}插入:boolListInsert(SqList&L,inti,inte){ if(i<1||i<L.length+1) //判断i的范围是否有......
  • 12月17日
    今天主要学习了Java中的输入输出(I/O)系统,这是Java编程中用于处理数据输入和输出的核心机制。I/O系统提供了丰富的类和接口,用于读取和写入文件、网络数据等,是实现程序与外部世界交互的重要工具。JavaI/O框架主要分为两个部分:字节流(ByteStreams)和字符流(CharacterStreams)。字节......