专栏文章

链表

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqhex7e
此快照首次捕获于
2025/12/04 04:51
3 个月前
此快照最后确认于
2025/12/04 04:51
3 个月前
查看原文

实现

构建链表

单向链表

单向链表中包含数据域和指针域,其中数据域用于存放数据,指针域用于连接当前节点和下一节点。
CPP
struct Node {
	int value;
	Node *next;
};

双向链表

双向链表中同样有数据域和指针域。不同之处在于,指针域有左右(或上一个、下一个)之分,用来连接上一个节点、当前节点、下一个节点。
CPP
struct Node {
	int value;	
	Node *left;
	Node *right;
};

向链表写入数据

单向链表

  1. 初始化待插入的数据 nodenode
  2. nodenodenextnext 指针指向 pp 的下一个节点;
  3. ppnextnext 指针指向 nodenode
CPP
void insert_node(int i, Node *p) {
	Node *node = new Node;
	node->value = i;
	node->next = p->next;
	p->next = node;
} 

单向循环链表

  1. 初始化待插入的数据 nodenode
  2. 判断给定链表 pp 是否为空;
  3. 若为空,则将 nodenodenextnext 指针和 pp 都指向自己;
  4. 否则,将 nodenodenextnext 指针指向 pp 的下一个节点;
  5. ppnextnext 指针指向 nodenode
CPP
void insert_node(int i, Node *p) {
	Node *node = new Node;
	node->value = i;
	node->next = NULL;
	if (p == NULL) {
		p = node;
		node->next = node;
	}
	else {
		node->next = p->next;
		p->next = node;
	}
}

双向循环链表

在向双向循环链表插入数据时,除了要判断给定链表是否为空外,还要同时修改左、右两个指针。
  1. 初始化待插入的数据 nodenode
  2. 判断给定链表 pp 是否为空;
  3. 若为空,则将 nodenodeleftleftrightright 指针,以及 pp 都指向自己;
  4. 否则,将 nodenodeleftleft 指针指向 pp;
  5. nodenoderightright 指针指向 pp 的右节点;
  6. pp 的右节点的 leftleft 指针指向 nodenode;
  7. pprightright 指针指向 nodenode
CPP
void insert_node(int i, Node *p) {
	Node *node = new Node;
	node->value = i;
	if (p == NULL) {
		p = node;
		node->left = node;
		node->right = node;
	}
	else {
		node->right = p;
		node->right = p->right;
		p->right->left = node;
		p->right = node;
	}
}

从链表中删除数据

单向(循环)链表 :

设待删除节点为 pp,从链表中删除它时,将 pp 的下一个节点 pnextp_{next} 的值覆盖给 pp 即可,从此同时更新 pp 的下下个节点。
  1. pp 的下一个节点的值赋给 pp,以抹掉 pvalue{p}_{value} ;
  2. 新建一个临时节点 tt 存放 pnextp_{next} 的地址 ;
  3. ppnextnext 指针指向 pp 的下下个节点,以抹掉 pnextp_{next} ;
  4. 删除 tt。此时虽然原节点 pp 的地址还在使用,删除的是原节点 pnextp_{next} 的地址,但 pp 的数据被 p>nextp->next 覆盖,pp 名存实亡。
CPP
void delete_node(Node *p) {
	p->value = p->next->value;
	Node *t = p->next;
	p->next = p->next->next;
	delete t;
}

双向循环链表

  1. pp 的左节点的右指针指向 pp 的右节点;
  2. pp 的右节点的左指针指向 pp 的左节点;
  3. 新建一个临时节点 tt 存放 pp 的地址;
  4. pp 的右节点地址赋值给 pp,以避免 pp 变成悬垂指针;
  5. 删除 tt
CPP
void delete_node(Node *&p) {
	p->left->right = p->right;
	p->right->left = p->left;
	Node *t = p;
	p = p->right;
	delete t;
}

技巧

异或链表

异或链表(XOR Linked List)本质上还是双向链表,但它利用按位异或的值,仅用一个指针的大小便可实现双向链表的功能。
在结构体 Node 中定义 lr=leftxorrightlr = left\operatorname{xor}right,即前后两个地址的按位异或值。正向遍历时用前一个元素的地址异或当前节点的 lrlr 可得到后一个元素的地址,反向遍历时用后一个元素的地址异或当前节点的 lrlr 又可得到前一个元素的地址。这样一来,便可以用一般的内存实现双向链表同样的功能。

评论

0 条评论,欢迎与作者交流。

正在加载评论...