删除单链表中重复的元素

今天同学突然让我帮他写个删除单链表中重复的元素这个程序,觉得很简单,就停下工作,写了一下。觉得在时间上,空间上都比较优化。 整体思路就是 遍历单链表,然后在判断当前节点是否在已访问的节点集合中,如果不在,说明该元素不重复,则将其插入到访问节点集合中,然后继续比较下一个节点,如果在其中,说明是重复出现,则从单链表中删除当前节点,然后继续比较下一个。 这里用了c++标准库中的set来保存访问过的元素,所以很方便的就可以判断当前节点是否在set集合中,直接使用set提供的find函数就可以了。而且使用set的查找在时间复杂度上比较低。 还有就是这里没有申请新的内存来存储新节点,而是直接在之前的单链表上进行操作,空间上不需要什么消耗。

#include <set>
#include <iostream>
#include <string>
using namespace std;
struct Data{
    string name;
};
//定义链表结构
struct Node{
    Data data;
    Node* next;
};
typedef Node* List;
//For test
string names[] = {"hello", "world", "hello","hello world", "zht","zhengh", "zht", "hello", "world", "hello world"};
void createList(List &list)
{
    list = new Node;
    list->data.name = "zhtsuc";
    List p = list;
    for(int i  = 0; i < 10; i++)
    {
        Node* node = new Node;
        node->data.name = names[i];
        p->next = node;
        p = node;
    }
    p->next = NULL;
}
void printList(List list)
{   
    List p = list;
    while(p != NULL)
    {
        cout << p->data.name << endl;
        p = p->next;
    }
}
int main(int argc, char* argv[])
{
    List list; 
    createList(list);
    set<string> allNames;    //保存所有不重复的name
   
    allNames.insert(list->data.name);  //首先,把第一个元素直接加进去。因为第一个不用比较
    List pre = list; //保存前一个指针
    List cur = list->next; //当前指针
    
    while(cur != NULL)
    {
        //如果在set中没有找到当前元素的name,则说明该记录不重复,将该记录的name加入到set,继续下一个
        if (allNames.find(cur->data.name) == allNames.end())
        {
            allNames.insert(cur->data.name);
            pre = cur;
            cur = cur->next;
        } 
        else 
        {
            //如果在set中找到当前元素的name,则说明重复,即删掉此元素,然后继续下一个
            Node* temp = cur; //先保存当前节点指针
            cur = cur->next;
            pre->next = cur; //改变指针指向,删除当前节点
            //在这里释放掉temp节点
            delete temp;
        }
    }
    printList(list); //这是我的测试代码
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值