数据结构考研真题(四)—— 删除单链表中绝对值相同的结点

一、问题描述

在这里插入图片描述

二、思路分析

这个问题,首先很容易想到要双重遍历,但是时间复杂度会比较高。那么我们可以考虑使用数组计数,这样就可以遍历一遍,这也算是一个比较好用的套路。

三、代码实现

3.1 第一种解法

void deleteDul(Link &link){
	Link cur = link->next;
	while(cur != NULL){
		Link next = cur;
		while(next != NULL && next->next != NULL){
			if(cur->data == next->next->data || -cur->data == next->next->data){
				next->next = next->next->next;
			}
			next = next->next;
		}	
		cur = cur->next;
	}
}

3.2 第二种解法

void deleteDul02(Link &link,int n){
	Link cur = link;
	int judge[n+1];
	for(int i=0;i<=n;i++){
		judge[i] = 0;
	}
	while(cur != NULL&&cur->next != NULL){
		int data = cur->next->data;
		if(judge[data] == 1 || judge[-data] == 1){
			cur->next = cur->next->next;
		}else{
			if(data < 0){
				data = -data;
			}
			judge[data] = 1;
			cur=cur->next;
		}
	}
}
算法思想: 1. 对于每个节点,将该节点的data的绝对值作为下标,插入到一个长度为m的数组。 2. 如果该下标对应的数组元素为空,则将该节点插入到该位置。 3. 如果该下标对应的数组元素不为空,则代表该位置已经存在节点的data的绝对值相等,需要将该节点从链表删除,并将该位置的节点更新为当前节点。 4. 遍历完整个链表后,将新生成的链表返回。 C程序实现如下: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAX_SIZE 100 // 定义节点结构体 typedef struct Node{ int data; struct Node *link; }Node; // 建立链表 Node *createList(int *arr, int n) { Node *head = (Node *)malloc(sizeof(Node)); Node *p = head; for (int i = 0; i < n; i++) { Node *node = (Node *)malloc(sizeof(Node)); node->data = arr[i]; node->link = NULL; p->link = node; p = node; } return head; } // 删除链表所有data相等的节点,仅保留第一个 Node *deleteDuplicate(Node *head) { Node *p = head->link; Node *q = head->link; Node *arr[MAX_SIZE] = {0}; while (p) { int index = abs(p->data) % MAX_SIZE; if (arr[index] == NULL) { arr[index] = p; q = p; } else { q->link = p->link; free(p); p = q->link; continue; } p = p->link; } return head; } // 打印链表 void printList(Node *head) { Node *p = head->link; while (p) { printf("%d ", p->data); p = p->link; } printf("\n"); } int main() { // 测试数据 int arr[5] = {1, 2, -3, 2, -1}; Node *head = createList(arr, 5); printf("原始链表:\n"); printList(head); head = deleteDuplicate(head); printf("删除重复节点后的链表:\n"); printList(head); return 0; } ``` 关键步骤注释说明如下: 1. 定义了节点的结构体,包括数据data和指向下一个节点的指针link: ```c typedef struct Node{ int data; struct Node *link; }Node; ``` 2. 建立链表时,每次创建一个新节点,并将该节点插入到链表的末尾: ```c Node *createList(int *arr, int n) { Node *head = (Node *)malloc(sizeof(Node)); Node *p = head; for (int i = 0; i < n; i++) { Node *node = (Node *)malloc(sizeof(Node)); node->data = arr[i]; node->link = NULL; p->link = node; p = node; } return head; } ``` 3. 删除链表所有data相等的节点,仅保留第一个。使用一个数组arr来保存data的绝对值作为下标对应的节点,如果该下标对应的数组元素为空,则将该节点插入到该位置;如果该下标对应的数组元素不为空,则代表该位置已经存在节点的data的绝对值相等,需要将该节点从链表删除,并将该位置的节点更新为当前节点: ```c Node *deleteDuplicate(Node *head) { Node *p = head->link; Node *q = head->link; Node *arr[MAX_SIZE] = {0}; while (p) { int index = abs(p->data) % MAX_SIZE; if (arr[index] == NULL) { arr[index] = p; q = p; } else { q->link = p->link; free(p); p = q->link; continue; } p = p->link; } return head; } ``` 4. 打印链表时,遍历链表的每个节点,并输出该节点的数据域data: ```c void printList(Node *head) { Node *p = head->link; while (p) { printf("%d ", p->data); p = p->link; } printf("\n"); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

索半斤_suobanjin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值