链表应用------PAT_A1097 Deduplication on a Linked List (25 分)

题目

1097 Deduplication on a Linked List (25 分)

Given a singly linked list L with integer keys, you are supposed to remove(删除) the nodes with duplicated absolute values(重复的绝对值) of the keys. That is, for each value K, only the first node of which the value or absolute value of its key equals K will be kept. At the mean time, all the removed nodes must be kept in a separate list. For example, given L being 21→-15→-15→-7→15, you must output 21→-15→-7, and the removed list -15→15.

给定一个链表,输出两个链表,一条是原来链表删掉绝对值重复的结点,另一条是被删除的结点按原来顺序输出。
首先输入开始结点位置begin、结点个数n
接着输入n个节点的address/data/next

思路

  1. 定义结构体,其中用order记录结点序号,可利用序号将结点分为有效结点、无效结点,有效结点又可分为保留结点和删除节点。
  2. 初始化结构体,order初始化为maxn*2,即刚开始全为无效结点
  3. 设置变量countValid记数保留结点,从0开始记;countRemoved记数删除节点,从maxn开始记。而无效结点是从maxn*2开始记,这样就将三种结点根据order不同分开了。遍历链表,用全局的bool 数组isExist记录绝对值第一次出现的情况。
  4. 排序。还是用sort,cmp规则是按照order大小来排序。
  5. 输出,最后一节点特殊处理,含-1.

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define maxn 100005
#define TABLE 1000010

struct Node{
	int address, data, next;
	int order;
}node[maxn];

bool isExist[TABLE] = {false};

bool cmp( Node a, Node b ){
	return a.order < b.order;
}

int main()
{
	//初始化
	memset( isExist, false, sizeof(isExist) );//不太明白
	for( int i = 0; i < maxn; i++ )
		node[i].order = 2*maxn;//无效结点标志为order==2*maxn
	//输入链表
	int n, begin, address;
	scanf( "%d%d",&begin, &n );
	for( int i=0; i<n; i++ ){
		scanf( "%d", &address );//地址需要先输入下面才可以调用
		scanf( "%d%d", &node[address].data, &node[address].next );
		node[address].address = address;
	 // scanf( "%d %d %d", &address, &data, &next );
	 // node[address].data = data;
     // node[address].next = next;
     // node[address].address = address;也可以这样写,需要再定义变量
	}
	//遍历链表
	int countValid = 0, countRemoved = 0, p = begin;
	while( p != -1 ){
		if( !isExist[abs(node[p].data)]){
			isExist[abs( node[p].data )]  = true;//绝对值第一次出现标为true
			node[p].order = countValid++;
		}else{
			node[p].order = maxn + countRemoved++;
		}
		p = node[p].next;
	}
	sort( node, node + maxn, cmp );
	//输出结果
	int count = countValid + countRemoved;
	for( int i=0; i<count; i++ ){
		if( i != count - 1 && i != countValid -1 ){
			printf("%05d %d %05d\n",node[i].address, node[i].data, node[i+1].address );
	//node[i].next已不指向输出顺序的下一结点了,此时已经排序完成,不再是给定的顺序
		}else{
			printf("%05d %d -1\n",node[i].address, node[i].data );
		}
	}
	return 0;
}

参考书籍《算法笔记》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值