【2015统考真题】用单链表保存m个整数,结点的结构为[data] [link],且|data|<=n(n为正整数)。现要求设计一个时间复杂度尽可能高动的管法,对干链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。例如,若给定的单链表head 如下:
代码思路:
这个说白了,就是链表版的去重,只不过这里的去重不仅仅是去除相同元素,连它的相反数也要去掉。我这里的思路就是,你用一个新链表,存储原先链表的元素,每次遍历原先链表元素,判断一下新链表中有无该元素的绝对值,如果有,就跳过,如果没有,你就插进去。
插完新链表,把新链表地址赋给原先链表,这样就完成了去重。
//判断当前链表L中是否有同元素a的绝对值的元素,有返回1,没有返回0
int contain(LinkList L, int a) {
LNode* p = L->next;
while (p != NULL) {
if (p->data == a||p->data==0-a) {
return 1;
}
p = p->next;
}
return 0;
}
//去除链表中绝对值重复
void del_CommonAbs(LinkList* L) {//删除链表中重复绝对值的元素
LinkList L2=(LNode*)malloc(sizeof(LNode));//将原先链表中不重复的部分放到L2中
LNode* p = (*L)->next;//用p遍历L
LNode* q=(LNode*)malloc(sizeof(LNode)) ;//用q遍历L2
//由于L中第一个元素是不可能重复的(第一个元素前面没有元素怎么重复?)
//直接把L中第一个元素放到L2中
q->data = p->data;
q->next = NULL;
L2->next = q;
//第一个L中第一个节点已经放到L2中了,我们从L第二个节点开始遍历
p = p->next;
while (p != NULL) {
int tmp = p->data;
if (!contain(L2, tmp)) {//如果原先L2里面没有当前遍历元素的的绝对值,把当前值放到L2中
q->next = (LNode*)malloc(sizeof(LNode));//新建一个L2节点
q = q->next;
q->data = tmp;
q->next = NULL;
}
p = p->next;
}
//L2装填完毕,把L2的值重新写回L
(*L) = L2;
}
int main()
{
LinkList L;
InitList2(&L);//初始化一个带头结点的链表 21,-15,-15,-7,15,2,3,2,2,9
printf("初始链表为:");
print2(L);
printf("\n");
printf("去除重复绝对值元素后的链表为:");
del_CommonAbs(&L);
print2(L);
return 0;
}