删除 开始->运行的记录

删除 开始->运行的记录

单击“开始→运行”,输入regedit,打开注册表编辑器,
找到HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU,
右击RunMRU项,选择“权限”,在“RunMRU的权限”窗口中点击“高级”按钮,选择“权限”选项卡,

在“权限项目”窗口中选择Administrators,再单击“编辑”按钮,
在“RunMRU的权限项目”的“权限”窗口,把Administrators用户对该注册表键的“完全控制”改为拒绝(如图),
退出注册表编辑器后即可让“运行”彻底失去记忆。


或HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU,删除右面的a,b,c...
<think>我们有一个链表,需要删除绝对值相同的节点(除了第一次出现的那个)。注意,这里绝对值相同可能是正数或负数。 例如,如果链表中有10和-10,那么我们应该保留第一次出现的那个(假设10先出现,则删除后面的-10;如果-10先出现,则删除后面的10)。 当前代码中,Implement函数的实现有误。它试图用两层循环,但内层循环从链表头开始,而且在内层循环中修改了链表结构(删除节点),这会导致问题。 正确的思路应该是: 1. 我们需要一个数据结构来记录已经出现过的绝对值。因为同一个绝对值,我们只保留第一次出现的节点。 2. 我们可以使用一个数组或者哈希表来记录已经出现过的绝对值。但题目没有说明整数的范围,我们可以使用一个哈希表(在C中,我们可以使用数组模拟,但更通用的是用哈希表,这里我们可以用简单的数组或者位图,但考虑到绝对值可能很大,我们可以用动态数组或者哈希集合。不过,题目没有明确,我们可以用哈希表(这里用数组可能不方便,因为不知道绝对值最大值)。 3. 另一种方法是使用两个指针,外层指针遍历每个节点,内层指针从当前节点往后遍历,检查是否有绝对值相同的节点。但是这种方法时间复杂度为O(n^2),但不需要额外空间。 由于题目没有明确要求空间复杂度,我们可以选择时间效率更高的哈希表(这里用数组模拟哈希集合)来记录已经出现的绝对值。但是注意,题目中整数的绝对值可能很大,我们可以使用一个布尔数组,但需要知道最大绝对值。如果不知道,我们可以使用一个哈希表(用链表或者开放寻址法)或者使用动态数组(如位图)但实现复杂。 考虑到题目没有给出数据范围,且链表节点数n可能较大,我们选择使用一个简单的数组来记录,但需要假设一个绝对值最大值(比如1000)。如果题目没有给出,我们可以使用动态扩展的数组或者使用链表来存储,但这样查找效率低。另一种方法是使用平衡二叉树,但C标准库没有内置,实现复杂。 因此,我们采用第二种方法:使用两个指针,外层指针遍历,内层指针检查后续节点是否有绝对值相同的节点,如果有则删除。这样时间复杂度为O(n^2),但空间复杂度为O(1)。 具体步骤: 1. 使用两个指针:p和q。p从第一个有效节点(head->next)开始,每次移动一步。 2. 对于每个p,我们使用另一个指针prev和q。prev指向p(因为我们要从p的下一个节点开始检查),q指向p->next。 3. 然后遍历q,如果q的绝对值等于p的绝对值(注意:这里p的绝对值是|p->El|,而q的绝对值是|q->El|),那么我们就删除q节点。删除时,需要将prev->next指向q->next,然后释放q,并让q重新指向prev->next(注意:此时prev不移动,因为可能连续有多个相同绝对值的节点)。 4. 如果q的绝对值不等于p的绝对值,那么prev和q都向后移动。 但是注意:题目要求保留第一次出现的节点。我们以p为基准,p是当前我们保留的节点,然后我们检查p之后的所有节点,删除所有绝对值等于|p->El|的节点。然后p移动到下一个节点,继续同样操作。 注意:这种方法会保留每个绝对值第一次出现的节点(因为p是从前往后遍历的,当p指向一个节点时,我们就认为这个节点是该绝对值的第一次出现(因为之前已经删除了与前面节点绝对值相同的节点?)),但实际上,我们并没有删除前面的节点。所以,我们需要确保:在p之前,相同的绝对值已经被处理过了吗?实际上,我们并没有。所以这种方法会保留每个绝对值第一次出现的节点(因为p遍历到某个节点时,如果这个节点的绝对值在之前已经出现过,那么它应该已经被删除了?不对,因为我们是从前往后,所以p节点本身是第一次出现的,我们只删除p后面绝对值相同的节点。这样,当p遍历整个链表时,每个绝对值第一次出现的节点都会被保留,并且删除了后面所有相同绝对值的节点。 因此,算法如下: 外层指针p从链表第一个节点开始,内层指针q从p的下一个节点开始,用prev指针记录q的前驱(这样方便删除)。当q不为空时,比较|q->El|和|p->El|,如果相等,则删除q节点(prev->next = q->next; free(q); q=prev->next;)。如果不相等,则prev和q都后移。 注意:由于我们删除的是后面的节点,所以不会影响p前面的节点。 我们修改Implement函数如下: 另外,注意链表带头节点。 但是,原代码中Implement函数的参数是node* L,而L是头节点。所以,我们这样写: 步骤: p = L->next; // 第一个有效节点 while (p != NULL) { node* prev = p; // 用于指向q的前驱,初始为p(因为q从p->next开始) node* q = p->next; while (q != NULL) { if (abs(q->El) == abs(p->El)) { // 需要包含stdlib.h以使用abs函数 // 删除q prev->next = q->next; free(q); q = prev->next; // 更新q,继续检查下一个节点 } else { prev = q; q = q->next; } } p = p->next; // 移动到下一个节点 } 但是注意:这种方法会删除所有后续相同绝对值的节点,包括多个相同绝对值的情况。 但是,我们考虑一下:如果链表是:10 -> -10 -> 15 -> 10 -> -10 首先p指向10(第一个节点),然后检查后面的节点:-10(绝对值10)等于10的绝对值,删除;然后下一个节点是15,保留;再下一个节点10,绝对值10等于10,删除;再下一个节点-10,已经被删除了,所以不会出现。 然后p移动到下一个节点(15),然后检查后面节点,没有绝对值15的节点,结束。 然后p移动到下一个节点(此时链表是10->15,因为第一个10后面删除-10和10,所以p->next已经是NULL了?不对,我们来看: 初始链表:头节点 -> 10 -> -10 -> 15 -> 10 -> -10 p指向10(第一个有效节点): q从-10开始: | -10 | = 10 == |10| -> 删除-10,链表变为:头节点->10->15->10->-10 q变为15(prev此时是10,q是10->next即15) 15的绝对值15 != 10 -> 则prev变为15,q变为10(即15的下一个节点) 10的绝对值10==10 -> 删除10,链表变为:头节点->10->15->-10 q变为-10(prev此时是15,q是15->next即-10) -10的绝对值10==10 -> 删除-10,链表变为:头节点->10->15 p移动到下一个节点(即15),然后检查15后面,没有节点了,结束。 这样,最后链表为10->15。 但是,我们要求保留第一次出现的节点,那么10是第一次出现的10,15是第一次出现的15,后面都删除了,符合要求。 但是,如果我们有:10 -> 20 -> -10 -> 30 按照上述算法: p指向10:检查后面的20、-10、30:发现-10的绝对值等于10,删除-10。链表变为10->20->30。 p指向20:检查后面30,没有绝对值20的节点。 p指向30:后面没有节点。 所以结果是10->20->30。 但是,如果链表是:-10 -> 20 -> 10 -> 30 p指向-10:绝对值10,检查后面20(绝对值20)不相等,保留;然后10(绝对值10)相等,删除10。链表变为-10->20->30。 然后p指向20,再指向30。所以保留-10,20,30。 所以,我们保留的是每个绝对值第一次出现的节点(不管正负)。 因此,我们修改Implement函数如下: 注意:需要包含stdlib.h以使用abs函数。 另外,原代码中,Implement函数没有使用abs,而是用了p->El==L->El或者p->El+L->El==0,这实际上就是判断相等或者互为相反数(即绝对值相等)。但这里我们使用abs更直接。 我们重新实现Implement函数: 同时,注意原代码中Implement函数的内层循环使用了L(头节点)作为指针,这会导致外层链表遍历和内存链表遍历混在一起,而且修改了L,这是错误的。 我们使用新的方法。 修改后的代码: */ #include <stdlib.h> // 为了使用abs函数 int Implement(node* L) { node* p = L->next; // 第一个有效节点 while (p != NULL) { node* prev = p; // 用于记录待比较节点的前一个节点,初始为p node* q = p->next; // 从p的下一个节点开始检查 while (q != NULL) { if (abs(q->El) == abs(p->El)) { // 删除q节点 prev->next = q->next; free(q); q = prev->next; // 更新q,继续检查下一个节点 } else { prev = q; q = q->next; } } p = p->next; // 移动到下一个节点 } return 1; } /* 但是,注意:原链表是带头节点的,所以我们的头节点不会改变。 现在,我们修改main函数中的测试数据,并运行。 测试数据1:10, -10, 15, 18, 60, -60, -21 期望结果:保留10,15,18,60,-21(因为10和-10绝对值相同,保留第一个10,删除-10;60和-60绝对值相同,保留60,删除-60;-21的绝对值21没有重复,保留) 所以输出应该是:10 15 18 60 -21 但是,按照我们的算法: 第一个节点10:检查后面节点,-10(绝对值10)删除,然后60(绝对值60)不等于10,保留,-60(绝对值60)不等于10,保留,-21(绝对值21)保留。 然后p移动到15:检查后面节点,18、60、-60、-21:没有绝对值15的节点,保留。 然后p移动到18:检查后面节点,60、-60、-21:没有绝对值18的节点,保留。 然后p移动到60:检查后面节点,-60(绝对值60)删除,然后-21保留。 然后p移动到-21:后面没有节点,结束。 所以链表为:10,15,18,60,-21 符合预期。 但是,注意:如果链表中有连续的相同绝对值,比如:10, -10, -10, 20 第一个节点10:删除后面第一个-10(链表变为10->-10->20),然后继续检查后面(现在是-10节点),它的绝对值10等于10,删除-10,链表变为10->20。 所以没有问题。 因此,我们使用这个实现。 但是,注意原代码中,在Implement函数中,我们使用了L作为头节点,但是我们在函数内部并没有修改L,而是用p和q在操作,所以不会影响头节点。 修改代码,并运行测试。 另外,原代码中,在main函数中,我们创建链表后调用Implement(L1),然后打印,最后销毁链表。 我们修改Implement函数为上述代码。 注意:原代码中已经包含了stdlib.h,所以可以使用abs函数。 但是,原代码中Ini_List函数创建的头节点El为0,这没有问题,因为头节点不存储有效数据。 现在,我们修改Implement函数,并测试。 另外,原代码中Print_List是从第一个有效节点开始打印,所以可以。 我们运行修改后的代码。 但是,注意:原代码中,在插入节点时,我们使用的是Ins_End,它是在链表尾部插入,所以链表顺序就是插入顺序。 测试数据:10, -10, 15, 18, 60, -60, -21 输出:10 15 18 60 -21 所以,修改后的代码如下: */</think>根据你的要求,我将实现一个函数来删除链表中绝对值相同的重复节点(只保留第一次出现的节点)。以下是完整的解决方案: ```c #include <stdio.h> #include <stdlib.h> typedef int Eltype; typedef struct Node { Eltype El; struct Node* next; } node; // 初始化链表头节点 node* Ini_List() { node* head = (node*)malloc(sizeof(node)); head->El = 0; // 头节点不存储有效数据 head->next = NULL; return head; } // 获取链表尾节点 node* Get_Tail(node* L) { node* p = L; while (p->next != NULL) { p = p->next; } return p; } // 在链表尾部插入新节点 int Ins_End(node* L, Eltype e) { node* p = Get_Tail(L); node* q = (node*)malloc(sizeof(node)); p->next = q; q->next = NULL; q->El = e; return 1; } // 销毁链表(释放所有节点内存) int Kill_List(node* L) { node* p = L->next; node* q; while (p != NULL) { q = p->next; free(p); p = q; } L->next = NULL; free(L); // 释放头节点 return 0; } // 打印链表内容 int Print_List(node* L) { node* p = L->next; while (p != NULL) { printf("%d ", p->El); p = p->next; } printf("\n"); return 1; } // 核心功能:删除绝对值重复的节点(保留首次出现的节点) int Implement(node* L) { // 使用数组记录已出现的绝对值(假设绝对值最大为1000) int abs_map[1001] = {0}; // 索引0不使用,1-1000对应绝对值1-1000 node* prev = L; // 前驱指针 node* current = L->next; // 当前指针 while (current != NULL) { int abs_val = abs(current->El); // 检查绝对值是否已存在 if (abs_val <= 1000 && abs_map[abs_val]) { // 删除重复节点 prev->next = current->next; free(current); current = prev->next; } else { // 标记该绝对值已出现 if (abs_val <= 1000) abs_map[abs_val] = 1; prev = current; current = current->next; } } return 1; } int main() { // 创建链表并插入测试数据 node* L1 = Ini_List(); Ins_End(L1, 10); Ins_End(L1, -10); Ins_End(L1, 15); Ins_End(L1, 18); Ins_End(L1, 60); Ins_End(L1, -60); Ins_End(L1, -21); printf("原始链表: "); Print_List(L1); // 执行去重操作 Implement(L1); printf("处理后的链表: "); Print_List(L1); // 清理内存 Kill_List(L1); return 0; } ``` ### 代码解释: 1. **链表结构**: - 使用带头节点的单链表结构,头节点不存储有效数据 - `Node`结构包含数据域`El`和指向下一个节点的指针 2. **辅助函数**: - `Ini_List()`: 初始化链表头节点 - `Get_Tail()`: 获取链表尾节点 - `Ins_End()`: 在链表尾部插入新节点 - `Print_List()`: 打印链表内容 - `Kill_List()`: 销毁链表并释放内存 3. **核心函数`Implement()`**: - 使用一个大小为1001的数组`abs_map`记录已出现的绝对值(索引1-1000对应绝对值1-1000) - 遍历链表,对每个节点计算其值的绝对值 - 如果该绝对值已记录,则删除当前节点 - 如果是首次出现,则标记该绝对值并保留节点 - 使用`prev`指针维护前驱节点关系,确保正确删除节点 4. **时间复杂度**: - 遍历链表一次,时间复杂度为O(n) - 空间复杂度为O(1)(使用固定大小的数组) 5. **注意事项**: - 假设节点值的绝对值不超过1000(可根据实际需求调整数组大小) - 包含`stdlib.h`头文件以使用`abs()`函数 - 正确处理了内存释放,避免内存泄漏 ### 示例输出: ``` 原始链表: 10 -10 15 18 60 -60 -21 处理后的链表: 10 15 18 60 -21 ``` 在这个输出中: - 保留了首次出现的10(绝对值10) - 删除了后续的-10(绝对值10) - 保留了首次出现的60(绝对值60) - 删除了后续的-60(绝对值60) - 保留了-21(绝对值21首次出现)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值