1.1 LeetCode总结(线性表)_链表类

编程总结

每每刷完一道题后,其思想和精妙之处没有地方记录,本篇博客用以记录刷题过程中的遇到的算法和技巧
在这里插入图片描述

链表基本操作

什么是链表,链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

链表的入口节点称为链表的头结点也就是head。

链表的类型
接下来说一下链表的几种类型:

#单链表
刚刚说的就是单链表。

typedef struct ListNodeT {
   
   
    int val;
    struct ListNodeT next;
} ListNode;

#双链表
单链表中的指针域只能指向节点的下一个节点。
双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。
双链表 既可以向前查询也可以向后查询。
如图所示: 链表2
在这里插入图片描述

#循环链表
循环链表,顾名思义,就是链表首尾相连。
循环链表可以用来解决约瑟夫环问题。
在这里插入图片描述

链表基础操作

typedef struct ListNode_t {
   
   
	int val;
	struct ListNode_t *next;
} ListNode;
// 1.创建链表
ListNode *ListCreate() {
   
   
	// 在链表的第一个结点之前会额外增设一个结点,头结点
	ListNode *head = (ListNode *)malloc(sizeof(ListNode));
	if (head == NULL) {
   
   
		return NULL;
	}
	head->next = NULL;
	head->val = 0; // 头结点的val用来指示链表长度
	return head;
}
// 2.获取链表中第index个节点的索引值,如果索引无效,则返回-1
int ListIndexGet(ListNode *obj, int index)
{
   
   
	int cnt = 0;
	ListNode *tmp = obj->next; // 手法:  因为我们是以首元结点开始index为0,所以要obj->next以首元开始
							   // 而不是 ListNode *tmp = obj; 
	while (tmp) {
   
   
		if (index == cnt) {
   
   
			return tmp->val;
		}
		cnt++;
		tmp = tmp->next;
	}
	return -1;
}

// 首元结点:链表中第一个元素所在的结点,它是头结点后边的第一个结点
/* 在链表的第一个元素之前添加值为val的节点。插入后,新节点将成为链表的第一个节点 */
/* obj -> node1 -> node2 */
/* obj -> newNode  -> node1 -> node2 */
void ListAddAtHead(ListNode *obj, int val)
{
   
   
	ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
	if (newNode == NULL) {
   
   
		return;
	}
	obj->val++; // 记录链表长度
	newNode->val = val;
	newNode->next = obj->next;
	obj->next = newNode;
}
/*  将值为val的节点附加到链表的最后一个元素 */
/*  head  -> node1 -> node2 */
/*  head  -> node1 -> node2 -> tail */
void ListAddAtTail(ListNode *obj, int val)
{
   
   
	ListNode *tail = (ListNode *)malloc(sizeof(ListNode));
	ListNode *tmp  = obj;
	if (tail == NULL) {
   
   
		return;
	}
	obj->val++; // 记录链表长度
	tail->val = val;
	tail->next = NULL;
	while (tmp->next) {
   
   
		tmp = tmp->next;
	}
	tmp->next = tail;
}
/* 在链表的索引节点之前添加一个值为val的节点。如果索引等于链表的长度,
   则节点将附加到链表的末尾。如果索引大于长度,则不会插入节点 */
/* obj -> node1 -> node2 */
/* obj -> node1 -> newNode -> node2 */
void ListAddAtIndex(ListNode *obj, int index, int val)
{
   
   
	int cnt = 0;
	if (index == obj->val) {
   
   
		ListAddAtTail(obj, val);
		return;
	} else if (index > obj->val) {
   
   
		return;
	}
	ListNode *tmp = obj;
	ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
	newNode->val = val;
	while (tmp) {
   
   
		if (cnt == index) {
   
   
			break;
		}
		tmp = tmp->next;
		cnt++;
	}
	obj->val++; // 记录链表长度
	newNode->next = tmp->next;
	tmp->next = newNode;
	return;
}
/* 如果索引有效,请删除链表中的第index个节点 */
/*  head  -> node1 -> node2 -> node3 */
/*  head  -> node1 -> node3          */
void ListDeleteAtIndex(ListNode *obj, int index)
{
   
   
	ListNode *node = NULL;
	ListNode *tmp = obj;
	int cnt = 0;
	while (tmp) {
   
   
		if (cnt == index) {
   
   
			break;
		}
		cnt++;
		tmp = tmp->next;
	}
	if (tmp->next == NULL) {
   
    // 删除的是最后的NULL,直接返回,手法
		return;
	}
	obj->val--;
	node = tmp->next;
	tmp->next = node->next;
	free(node);
}
/*  head  -> node1 -> node2 -> node3 */
void ListFree(ListNode *obj)
{
   
   
	ListNode *tmp = obj;
	ListNode *freeNode;
	while (tmp) {
   
     // 释放头结点->首元结点内的
		freeNode = tmp;
		tmp = tmp->next;
		freeNode->next = NULL;
		freeNode->val = 0;
		free(freeNode);
	}
}

203. 删除链表的节点_ED

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
在这里插入图片描述
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1
输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7
输出:[]

提示:
列表中的节点数目在范围 [0, 104] 内
1 <= Node.val <= 50
0 <= val <= 50

用 temp 表示当前节点。如果 temp 的下一个节点不为空且下一个节点的节点值等于给定的 val,则需要删除下一个节点。
删除下一个节点可以通过以下做法实现:temp.next=temp.next.next
如果 temp 的下一个节点的节点值不等于给定的 val,则保留下一个节点,将 temp 移动到下一个节点即可。当 temp 的下一个节点为空时,链表遍历结束,此时所有节点值等于 val 的节点都被删除。
具体实现方面,由于链表的头节点 head 有可能需要被删除,因此创建哑节点 dummyHead,令 dummyHead.next=head,初始化 temp=dummyHead,然后遍历链表进行删除操作。最终返回 dummyHead.next 即为删除操作后的头节点

创建虚拟头结点,来处理

// dummyHead -> head 
//              temp -> (temp->next) -> (temp->next->next)
struct ListNode *removeElements(struct ListNode *head, int val)
{
   
   
	struct ListNode *dummy_head = (struct ListNode *)malloc(sizeof(struct ListNode));
	dummy_head->next = head;
	struct ListNode *cur = dummy_head;
	// dummy_head是哑节点,看的是 cur->next 节点
	while ((cur->next != NULL)) {
   
   
		if (cur->next->val == val) {
   
   
			cur->next = cur->next->next;
		} else {
   
   
			cur = cur->next
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值