题目描述
给定n个整数,按输入顺序建立单链表,删除其中的重复数字,输出结果链表。(要求不可以构建新结点,不可以定义新链表。在原链表上删除。)
输入
测试次数t
每组测试数据一行:
n(表示有n个整数),后跟n个数字
输出
对每组测试数据,输出删除重复数字后的结果链表表长和每个元素,具体格式见样例。
输入样例:
3
10 1 2 3 4 1 2 10 20 30 20
5 1 1 1 1 1
6 20 22 22 22 22 20
输出样例:
7: 1 2 3 4 10 20 30
1: 1
2: 20 22
代码看着很长,很多都是之前的内容,主要是新写一个删除重复元素的函数。
#include<iostream>
using namespace std;
class ListNode {
public:
int data;
ListNode* next;
ListNode() { next = NULL; data = 0; }
};
//带头结点的单链表类定义
class LinkList {
public:
ListNode* head;
int len;
//操作定义
LinkList();
~LinkList();
ListNode* LL_index(int i);//返回第i个结点的指针,如果不存在返回NULL
int LL_insert(int i, int item);//把数值item插入第i个位置
int LL_del(int i);//删除第i个结点
void delrepeat();
void LL_disply();//输出单链表的内容
};
LinkList::LinkList() {
head = new ListNode();
len = 0;
}
LinkList::~LinkList() {
ListNode* p, * q;
p = head;
while (p != NULL) {
q = p;
p = p->next;
delete q;
}
len = 0;
head = NULL;
}
ListNode* LinkList::LL_index(int i) {//由于这里没有把head结点看做第0个结点
if (i > len || i < 1) { //因此head结点的申请需要另外操作
return NULL; //数据不规范,返回error
}
ListNode* p = head->next; //初始结点就是第一个结点
for (int k = 1; k < i; k++) {//如果找第一个节点,就不用进入循环
p = p->next; //找第i个结点,循环i-1次
}
return p;
}
int LinkList::LL_insert(int i, int item) {
if (i<1 || i>len + 1) {//数据不合法
return 0;
}
ListNode* p;
if (i == 1) {//因为LL_index函数不会找到head结点,所以特殊处理
p = head;//这一点如果不想特殊处理,就去改一下index函数,head结点当做第0个结点
}
else {
p = LL_index(i - 1);//找到第i-1个结点
}
ListNode* q = new ListNode;//生成空间
q->data = item;//赋值
q->next = p->next;//把第i-1个结点的后一个结点变成q结点的后一个结点
p->next = q;//把第i-1个结点的next设置为q
len++;//长度增加
return 1;
}
int LinkList::LL_del(int i) {
if (i<1 || i>len) {//数据不合法
cout << "error" << endl;
return 0;
}
ListNode* p;
if (i == 1) {
p = head;//和上面插入一样,对该情况特殊处理
}
else {
p = LL_index(i - 1);//找第i-1个结点
}
ListNode* temp = p->next;//提前保存第i个结点的指针
ListNode* q = temp->next;//q为第i+1个结点
p->next = q;//直接把第i-1个结点的next指向第i+1个结点
len--;//长度减少
free(temp);//释放掉原来的第i个结点
//LL_disply();
return 1;
}
void LinkList::delrepeat() {
ListNode* p = head->next->next;//p结点指向第2个结点(把head结点看做0)
int temp = p->data;//保留p结点的值
int i = 2;//我们从第二个结点开始找重复,因为第一个结点绝对不会重复
int j;
while (p) {//p为空时跳出
for (j = 1; j < i; j++) {//从第一个结点到p前面一个结点
if (LL_index(j)->data == temp) {//查看结点数据是否重复
p = p->next;//把p挪向下一个结点
LL_del(i);//删除掉原来的p结点
if (p) temp = p->data;//这里加if是因为当进行到最后一个节点
break; //跳出 //,接上一句:此时p为空,不存在data
}
}
if (j == i) {//表明不存在重复
p = p->next;//p进行到下一个结点
temp = p->data;//存入p的值
i++;//存入i的下标,注意:只有这种情况i++,因为其他情况会删除一个结点
} //接上一句:导致len减一,下标就不能加
}
}
void LinkList::LL_disply() {
ListNode* p;
p = head->next;
cout << len << ":";
while (p) {
cout <<' '<<p->data;
p = p->next;
}
cout << endl;
}
int main() {
int t;
int len,item;
cin >> t;
while (t--) {
LinkList list;
cin >> len;
for (int i = 1; i <= len; i++) {
cin >> item;
list.LL_insert(i, item);
}
//list.LL_disply();
list.delrepeat();
list.LL_disply();
}
}