//链表删除重复的元素
#include <iostream>
using namespace std;
struct node
{
int data;
struct node *next;
};
//逆序建立链表
void createlist(struct node *L, int x)
{
struct node *p;
p = (node*)malloc(sizeof(node));
p->data = x;
p->next = L->next;
L->next = p;
}
void display(struct node *L)
{
struct node *p = L->next->next;
cout << L->next->data;
while (p != NULL)
{
cout << ' ' << p->data;
p = p->next;
}
cout << endl;
}
//删除重复的元素为单一元素
//使用类似于选择排序里的遍历逻辑
void del(struct node *L)
{
struct node *t, *q, *p;
t = L->next;
q = t;
p = t->next;
//t来遍历所有节点
while (t->next != NULL)
{
//使用p、q轮流 ,找t之后的和t里的值相同的节点,释放掉。
while (p != NULL)
{
if (p->data == t->data)
{
q->next = p->next;
free(p);
p = q->next;
}
else
{
p = p->next;
q = q->next;
}
}
t = t->next;
p = t->next;
q = t;
}
}
int main()
{
int n;
struct node *L;
L = (struct node *)malloc(sizeof(struct node));
L->next = NULL;
cin >> n;
while (n--)
{
int x;
cin >> x;
createlist(L, x);
}
del(L);
display(L);
return 0;
}
有人问del函数里面 free(p) 了,为什么后面还可以 p = q ->next ?
解答:
1)free只是释放了malloc所申请的内存,并没有改变指针的值;
2)由于指针所指向的内存空间已经被释放,所以其他代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的区域(无法控制这么说还是可以去使用的,只是危险),也成为野指针(野指针指指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为NULL避免)。
3)为了避免错误,所以最好在free之后,使指针指向NULL。
根据原理的解释分析:free函数的作用只是告诉操作系统该内存不用了,可以收回,操作系统就把该内存链接到链接表上,
但是这段内存用户还是可以访问到的,只是该内存的值可能已经发生了变化。
源自:https://blog.youkuaiyun.com/localhostcom/article/details/87252174