访问次数:

Wenji's blog
头部背景图片
WenJi's blog |
WenJi's blog |

dwjdwjdw基于链表的两个递增有序序列的合并

2021-10-21

注意,这题我一直由于没搞清指针和地址的差别而出问题

描述
给定两个递增的整数序列A和B,利用链表表示序列A和B,将A和B合并为一个递增的有序序列C,序列C不允许有重复的数据。要求空间复杂度为O(1)。

输入
多组数据,每组数据有三行,第一行为序列A和B的长度n和m,第二行为序列A的n个元素,第三行为序列B的m个元素(元素之间用空格分隔)。n=0且m=0时输入结束。

输出
对于每组数据输出一行,为合并后的序列,每个数据之间用空格分隔。

样例输入1 复制
5 5
1 3 5 7 9
2 4 6 8 10
3 4
1 5 9
1 2 5 9
0 0
样例输出1
1 2 3 4 5 6 7 8 9 10
1 2 5 9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#define OK 1
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
bool InintList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
void mergelist(LinkList &L,LinkList &S,LinkList &T)
{
LNode *p1=L->next;
LNode *p2=S->next;
//LNode *p3=T->next;//误区
LNode *p3=T;//因为要用next来串联
LNode *p4;
while(p1&&p2)
{
if(p1->data<p2->data)
{
/*p3=p1;
p3=p3->next;
p1=p1->next;*///始终要记住p3是一个指针,指向可以变,而每个指针的next才是真正不会变的
p3->next=p1;
p3=p1;
p1=p1->next;
}
else if(p1->data>p2->data)
{
p3->next=p2;
p3=p2;
p2=p2->next;

}
else
{
p3->next=p1;
p3=p1;
p1=p1->next;
p4=p2;
p2=p2->next;
delete p4;
}
}
p3->next=p1?p1:p2;
delete S;
}
int main()
{
LNode *p1;
LNode *p2;
int num1,num2;
while(cin>>num1>>num2&&!(num1==0&&num2==0))
{
LinkList L;
LinkList S;
LinkList T;
InintList(L);
InintList(S);
InintList(T);
L->next=new LNode;
S->next=new LNode;
LNode *p1=L->next;
LNode *pre1=L;
LNode *p2=S->next;
LNode *pre2=S;
for(int i=1;i<=num1;i++)
{
cin>>p1->data;
p1->next=new LNode;
p1=p1->next;
pre1=pre1->next;
}
pre1->next=NULL;
for(int i=1;i<=num2;i++)
{
cin>>p2->data;
p2->next=new LNode;
p2=p2->next;
pre2=pre2->next;
}
pre2->next=NULL;
mergelist(L,S,T);
LNode *p=T->next;
cout<<p->data;
p=p->next;
while(p)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;
}
return 0;
}

基于快排思想的查找

2018-12-15

描述
借助于快速排序的算法思想,在一组无序的记录中查找给定关键字值等于key的记录。设此组记录存放于数组r[l..n]中。若查找成功,则输出该记录在r数组中的位置及其值,否则显示“not find”信息。

输入
多组数据,每组数据三行。第一行为序列的长度n,第二行为序列的n个元素(元素之间用空格分隔,元素都为正整数),第三行为要查找的key值。当n等于0时,输入结束。

输出
每组数据输出一行。如果查找成功,输出key在数组中的位置(1到n)和key的值,两个数字之间用空格隔开。如果查找失败,输出“not find”。

样例输入1 复制
5
1 2 43 5 6
43
4
1 9 20 3
21
7
20 30 40 10 1 2 3
10
0
样例输出1
3 43
not find
4 10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<iostream>
using namespace std;
int search(int r[],int low,int high,int key)
{
while(low<high)
{
while(r[low]>key&&r[high]<key)
{
high--;
low++;
}
while(low<=high&&r[high]>key) high--;
if(r[high]==key)
return high+1;
while(low<=high&&r[low]<key) low++;
if(r[low]==key) return low+1;
}
return 0;
}
int main()
{
int a[100];
while(1)
{
int n;
cin>>n;
if(n==0)
break;
else
{
for(int i=0;i<n;i++)
{
cin>>a[i];
}
int key;
cin>>key;
int flag=search(a,0,n-1,key);
if(flag==0)
cout<<"not find"<<endl;
else
{
cout<<flag<<" "<<key<<endl;
}
}
}
return 0;
}

基于双向链表的双向冒泡排序法

2018-12-15

描述
有n个记录存储在带头结点的双向链表中,利用双向冒泡排序法对其按上升序进行排序,请写出这种排序的算法。(注:双向冒泡排序即相邻两趟排序向相反方向冒泡)。

输入
多组数据,每组数据两行。第一行为序列的长度n,第二行为序列的n个元素(元素之间用空格分隔,元素都为正整数)。当n等于0时,输入结束。

输出
每组数据输出一行,为从小到大排序后的序列。每两个元素之间用空格隔开。

样例输入1 复制

5
4 5 3 2 9
6
1 3 5 7 9 2
0
样例输出1
2 3 4 5 9
1 2 3 5 7 9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include<iostream>
using namespace std;
typedef struct DuLNode
{
int data;
struct DuLNode *pre,*next;
}DuLNode,*DuLinkList;
void DuplexSort(DuLinkList &L)
{
int exchange=1;//判断是否还能交换
DuLNode *head=L;
DuLNode *tail=NULL;
DuLNode *p;
while(exchange)
{
p=head->next; //p是工作指针,指向当前结点
exchange=0; //假设没交换,那么就是排好序的,那么就不用在冒泡
while(p->next!=tail)
{
if(p->data>p->next->data)//上升序列大的沉底
{
DuLNode *temp=p->next;
exchange=1; //有一次交换就说明之前不是排好序的
p->next=temp->next;//双向链表的交换
if(temp->next)temp->next->pre=p;//这里可能存在temp->next=NULL的情况
temp->next=p;
p->pre->next=temp;
temp->pre=p->pre;
p->pre=temp;
}
else p=p->next;
}
tail=p; //反向冒泡
p=tail->pre;
while(exchange&&p->pre!=head)
{
if(p->data<p->pre->data)
{
DuLNode *temp=p->pre;
exchange=1;
p->pre=temp->pre;
temp->pre->next=p;
temp->pre=p;
p->next->pre=temp;
temp->next=p->next;
p->next=temp;
}
else p=p->pre;
}
head=p;
}

}
int main()
{
while(1)
{
int n;
cin>>n;
if(n==0)
break;
else
{
DuLinkList L=new DuLNode;
L->next=NULL;
L->pre=NULL;
DuLNode *rear=L;
for(int i=0;i<n;i++)
{
DuLNode *p=new DuLNode;
p->next=NULL;
cin>>p->data;
rear->next=p;
p->pre=rear;
rear=p;
}
DuplexSort(L);
DuLNode *pp=L->next;
while(pp)
{
if(pp->next!=NULL)
cout<<pp->data<<" ";
else
cout<<pp->data<<endl;
pp=pp->next;
}
}
}
return 0;
}

基于哈夫曼树的数据压缩算法

2018-11-20

描述
输入一串字符串,根据给定的字符串中字符出现的频率建立相应哈夫曼树,构造哈夫曼编码表,在此基础上可以对待压缩文件进行压缩(即编码),同时可以对压缩后的二进制编码文件进行解压(即译码)。

输入
多组数据,每组数据一行,为一个字符串(只考虑26个小写字母即可)。当输入字符串为“0”时,输入结束。

输出
每组数据输出2n+3行(n为输入串中字符类别的个数)。第一行为统计出来的字符出现频率(只输出存在的字符,格式为:字符:频度),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。第二行至第2n行为哈夫曼树的存储结构的终态(形如教材139页表5.2(b),一行当中的数据用空格分隔)。第2n+1行为每个字符的哈夫曼编码(只输出存在的字符,格式为:字符:编码),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。第2n+2行为编码后的字符串,第2n+3行为解码后的字符串(与输入的字符串相同)。

样例输入1 复制
aaaaaaabbbbbccdddd
aabccc
0
样例输出1
a:7 b:5 c:2 d:4
1 7 7 0 0
2 5 6 0 0
3 2 5 0 0
4 4 5 0 0
5 6 6 3 4
6 11 7 2 5
7 18 0 1 6
a:0 b:10 c:110 d:111
00000001010101010110110111111111111
aaaaaaabbbbbccdddd
a:2 b:1 c:3
1 2 4 0 0
2 1 4 0 0
3 3 5 0 0
4 3 5 2 1
5 6 0 3 4
a:11 b:10 c:0
111110000
aabccc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
#define MAXSIZE 1000
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef struct
{
char ss[31]; //哈夫曼编码数组,设31是为了以防二进制编码过长
int start;
}HCode;
void Select(HuffmanTree &HT,int m,int &ll,int &rr)//ll的weight小于等于rr的weight,且在数组中又先后顺序。
{
int maxsize=1000; //判断大小的最大值
for(int i=1;i<=m;i++)
{
if(HT[i].parent==0&&maxsize>HT[i].weight)//为>,不是>=,保证遇到第一个编号保留下来。
{
ll=i;
maxsize=HT[i].weight;
}
}
maxsize=1000;
for(int i=1;i<=m;i++)
{
if(HT[i].parent==0&&i!=ll&&maxsize>HT[i].weight)//同理不是>=
{
maxsize=HT[i].weight;
rr=i;
}
}
}
void CreateHuffmanTree(HuffmanTree &HT,int n,int num[]) //创建哈夫曼树
{
if(n<=0) return;
int m=2*n-1;
HT=new HTNode[m+1];
for(int i=1;i<=m;i++)
{
HT[i].parent=0;HT[i].rchild=0;HT[i].lchild=0;
}
int start=1;
for(int i=0;i<26;i++)
{
if(num[i]>0)
{
HT[start++].weight=num[i];
}
}
for(int i=n+1;i<=m;i++)
{
int s1,s2;
Select(HT,i-1,s1,s2);
HT[s1].parent=i;HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
}
void CreateHCode(HuffmanTree &HT,HCode s[],int num[],int n)
{
int jstart=1; //哈弗曼编号,即在HT数组里面存在
for(int i=0;i<26;i++)
{
s[i].start=30; //给start初始化
if(num[i]>0)
{
int jj=jstart;
if(n==1) //控制如果为一个节点的特殊情况如何编码
s[i].ss[s[i].start--]='0';
else
{
while(HT[jj].parent!=0)
{
if(HT[HT[jj].parent].lchild==jj)
{s[i].ss[s[i].start--]='0'; //编码是一个入栈,出栈的过程
jj=HT[jj].parent;
}
else
{s[i].ss[s[i].start--]='1';
jj=HT[jj].parent;
}
}
}
jstart++;
}
}
}
int main()
{
string str;
int num[30];
while(cin>>str)
{
int n=0;//这里一定要赋值为0,不然这个n一直在循环里存在,bug都找不到,我太粗心了。
memset(num,0,sizeof(num));
if(str[0]=='0')
break;
for(int i=0;i<str.length();i++)
{
int a=int(str[i])-97;
num[a]++;
}
char b;
int j; //j为暂时变量,存储位置
for(int i=0;i<26;i++)
{
if(num[i]>0) //输出控制num数组很重要
{
b=char(i+97);
cout<<b<<":"<<num[i];
j=i;
n++;
break;
}

}
for(int i=j+1;i<26;i++)
{
if(num[i]>0)
{
b=char(i+97);
n++;
cout<<" "<<b<<":"<<num[i];
}
}
cout<<endl;
HuffmanTree HT;
int m=2*n-1;
CreateHuffmanTree(HT,n,num);
for(int i=1;i<=m;i++)
{
cout<<i<<" "<<HT[i].weight<<" "<<HT[i].parent<<" "<<HT[i].lchild<<" "<<HT[i].rchild<<endl;
}
HCode s[30]; //26个字母的哈夫曼编码
CreateHCode(HT,s,num,n);
for(int i=0;i<26;i++)
{
if(num[i]>0)
{
b=char(i+97);
cout<<b<<":";
for(int k=s[i].start+1;k<=30;k++)
{
cout<<s[i].ss[k];
}
j=i;
break;}
}
for(int i=j+1;i<26;i++)
{
if(num[i]>0)
{
b=char(i+97);
cout<<" "<<b<<":";
for(int k=s[i].start+1;k<=30;k++)
{
cout<<s[i].ss[k];
}
}
}
cout<<endl;
for(int i=0;i<str.length();i++)
{
int p=int(str[i])-97;
for(int k=s[p].start+1;k<=30;k++)
cout<<s[p].ss[k];
}
cout<<endl;
cout<<str<<endl;
str.clear();
}
return 0;
}

基于栈的中缀算术表达式求值

2018-11-04

描述
输入一个中缀算术表达式,求解表达式的值。运算符包括+、-、*、/、(、)、=,参加运算的数为double类型且为正数。(要求:直接针对中缀算术表达式进行计算,不能转换为后缀或前缀表达式再进行计算,只考虑二元运算即可。)

输入
多组数据,每组数据一行,对应一个算术表达式,每个表达式均以“=”结尾。当表达式只有一个“=”时,输入结束。参加运算的数为double类型。

输出
对于每组数据输出一行,为表达式的运算结果。输出保留两位小数。

样例输入1 复制
2+2=
20*(4.5-3)=
=
样例输出1
4.00
30.00

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define MAXSIZE 100
#define OK 1
using namespace std;
typedef struct
{
char *base;
char *top;
int stacksize;
}CharStack;//运算符
typedef struct
{
double *base;
double *top;
int stacksize;
}NumStack;//数字
bool InitStack(CharStack &S)
{
S.base=new char[MAXSIZE];
S.top=S.base;
S.stacksize=MAXSIZE;
return OK;
}
bool InitStack(NumStack &S)
{
S.base=new double[MAXSIZE];
S.top=S.base;
S.stacksize=MAXSIZE;
return OK;
}
bool Push(CharStack &S,char e)
{
*S.top++=e;
return OK;
}
bool Push(NumStack &S,double e)
{
*S.top++=e;
return OK;
}
bool Pop(CharStack &S)
{
--S.top;
return OK;
}
bool Pop(NumStack &S)
{
--S.top;
return OK;
}
char GetTop(CharStack &S)
{
return *(S.top-1); //顺序表中的可以进行加减来移位
}
double GetTop(NumStack &S)
{
return *(S.top-1);
}
char Precede(char a,char b)
{
if((a=='('&&b==')')||(a=='='&&b=='='))
return '=';
else if(a=='('||a=='='||b=='('||((a=='+'||a=='-')&&(b=='*'||b=='/')))
return '<';
else
return '>';
}
double Fun(double a,double b,char oper)
{
if(oper=='+')
return b+a;
else if(oper=='-')
return b-a;
else if(oper=='*')
return b*a;
else if(oper=='/')
return b/a;
}
int main()
{
char s[100];
while(1)
{
cin>>s;
if(s[0]=='=')
break;
NumStack SNum;//数字栈
CharStack SChar;//运算符栈
InitStack(SNum);
InitStack(SChar);
Push(SChar,'=');//表达式结束符为'=',所以压进去,为了之后与表达式的'='进行比较来清空SChar
int flag=0;
int x=0;
int e=0;//记录小数点的位置,数位
double y=0;
double a,b;//弹出的两个数字
double c;//c为a和b得出
char oper;//弹出的运算符
for(int i=0;s[i]!='\0';i++)
{
if(s[i]>='0'&&s[i]<='9')
{
flag=1;
x=x*10+s[i]-'0';
if(e)
{
e*=10;
}
}
else if(s[i]=='.')
{
e=1;
}
else
{
if(flag)
{
if(e)
y=x*1.0/e;
else
y=x*1.0;
Push(SNum,y);
x=0;
e=0;
flag=0;
}
while(1)
{
if(Precede(GetTop(SChar),s[i])=='<')
{
Push(SChar,s[i]);
break;
}
else if(Precede(GetTop(SChar),s[i])=='>')
{
a=GetTop(SNum);
Pop(SNum);
b=GetTop(SNum);
Pop(SNum);
oper=GetTop(SChar);
Pop(SChar);
c=Fun(a,b,oper);
Push(SNum,c);
}
else
{
Pop(SChar);
break;
}
}
}
}
printf("%.2f\n",GetTop(SNum));
}
return 0;
}

删除链表中满足区间值的结点

2018-10-22

描述
利用单链表表示一个递增的整数序列,删除链表中值大于等于mink且小于等于maxk的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同,也可以不同)。

输入
多组数据,每组数据有两行,第一行为链表的长度n,第二行为链表的n个元素(元素之间用空格分隔),第三行为给定的mink和maxk(用空格分隔)。当n=0时输入结束。

输出
对于每组数据分别输出一行,依次输出删除元素后的链表元素,元素之间用空格分隔。

样例输入1 复制
5
1 2 3 4 5
2 4
6
2 4 6 8 10 12
3 5
0
样例输出1
1 5
2 6 8 10 12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include<iostream>
#define OK 1
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
bool InintList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
/*
void DeleteMinMax(LinkList &L,int mink,int maxk) //自己的解法,没有老师的简便和合理
{
LNode *p=L->next;
LNode *t1=L,*t2=L->next;//暂时记录位置的指针 ,这个一定要注意初始化,不然可能会造成空指针,由于第一个节点可能被删除
LNode *t;//暂时记录位置
while(p->data<mink)
{
t1=p;
p=p->next;
}
while(p) //比较关键的一步
{
if(p->data<=maxk)
t2=p;
p=p->next;
}
t1->next=t2->next; //连接
p=t1->next;
while(p!=(t2->next)) //关键步骤
{
t=p;
p=p->next;
delete t;
}
}*/
void DeleteMinMax(LinkList &L,int mink,int maxk)//官方解法
{
LNode *pre=L; //
LNode *p=L->next;
LNode *q,*s;//暂时指针
while(p&&p->data<mink)
{
pre=p;
p=p->next;
}
while(p&&p->data<=maxk)
{
p=p->next;
}
q=pre->next;
pre->next=p;//连接完成,接下来是delete。
while(q!=p)
{
s=q;
q=q->next;
delete s;
}
}
int main()
{
int num;
while(cin>>num&&num!=0)
{
LinkList L;
InintList(L);
LNode *p;
LNode *r;
r=L;
for(int i=1;i<=num;i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
int mink,maxk;
cin>>mink>>maxk;
DeleteMinMax(L,mink,maxk);
p=L->next;
cout<<p->data;
p=p->next;
while(p)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;
}
return 0;
}

链表的逆转(前插法逆转)

2018-10-22

描述
利用单链表表示一个整数序列,通过一趟遍历,将单链表中所有结点的链接方向逆转。要求空间复杂度为O(1)。

输入
多组数据,每组数据有两行,第一行为链表的长度n,第二行为链表的n个元素(元素之间用空格分隔)。当n=0时输入结束。

输出
对于每组数据分别输出一行,逆序输出链表中的元素,元素之间用空格分隔。

样例输入1 复制
5
1 2 3 4 5
6
3 1 2 5 4 6
0
样例输出1
5 4 3 2 1
6 4 5 2 1 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<iostream>
#define OK 1
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
bool InintList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
void Inverse(LinkList &L)//前插法逆转
{
LNode *p=L->next;
L->next=NULL;
LNode *t;//暂时指针
while(p)
{
t=p->next;
p->next=L->next;
L->next=p;
p=t;
}
}
int main()
{
int num;
while(cin>>num&&num!=0)
{
LinkList L;
InintList(L);
LNode *p;
LNode *r;
r=L;
for(int i=1;i<=num;i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
Inverse(L);
p=L->next;
cout<<p->data;
p=p->next;
while(p)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;
}
return 0;
}

链表的分解

2018-10-22

描述
利用单链表A表示一个非零整数序列,把A分解为两个具有相同结构的链表B和C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点。要求空间复杂度为O(1),链表B和C均利用链表A的结点空间。

输入
多组数据,每组数据有两行,第一行为链表A的长度n,第二行为链表A的n个元素(元素之间用空格分隔)。当n=0时输入结束。

输出
对于每组数据分别输出两行,分别对应链表B和C的元素,每个数据之间用空格分隔。

样例输入1 复制
7
3 -6 1 -2 4 -3 8
8
2 5 3 -1 -2 2 6 -1
0
样例输出1
-6 -2 -3
3 1 4 8
-1 -2 -1
2 5 3 2 6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include<iostream>
#define OK 1
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
bool InintList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
void Decompose(LinkList &L,LinkList &La,LinkList &Lb)
{
La=L;
InintList(Lb);//用了空间O(1),La继承L的头节点
LNode *p=L->next;//注意从L->next开始,不是L,不然while里面会报错
LNode *pa=La;
LNode *pb=Lb;
while(p)
{
if(p->data<0) //题上已说非零的L链表
{
pa->next=p;
pa=p;
p=p->next;
}
else
{
pb->next=p;
pb=p;
p=p->next;
}
}
pa->next=NULL;
pb->next=NULL;
}
int main()
{
int num;
while(cin>>num&&num!=0)
{
LinkList L;
InintList(L);
LinkList La;
LinkList Lb;
LNode *p;
LNode *r;
r=L;
for(int i=1;i<=num;i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
Decompose(L,La,Lb);
p=La->next;
cout<<p->data;
p=p->next;
while(p)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;
p=Lb->next;
cout<<p->data;
p=p->next;
while(p)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;
}
return 0;
}

基于链表的两个集合的差集

2018-10-22

描述
给定两个递增的整数集合,分别用链表A和B表示,求出A和B的差集(即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。要求空间复杂度为O(1)。

输入
多组数据,每组数据有三行,第一行为序列A和B的长度n和m,第二行为序列A的n个元素,第三行为序列B的m个元素(元素之间用空格分隔)。n=0且m=0时输入结束。

输出
对于每组数据输出两行,第一行是A和B的差集,第二行为差集中的元素个数,每个数据之间用空格分隔。

样例输入1 复制
5 5
1 3 5 7 9
1 2 3 4 5
3 4
1 2 6
2 4 5 7
0 0
样例输出1
7 9
2
1 6
2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<iostream>
#define OK 1
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
bool InintList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
void Difference(LinkList &La,LinkList &Lb,int &n)//求两个递增序列的差集 (La-Lb)
{
LNode *pa=La->next;
LNode *pb=Lb->next;
LNode *pre=La;
LNode *t;//暂时指针
while(pa)
{
if((pb&&(pa->data<pb->data))||(!pb&&pa))//如果pa比pb长的话 ,条件判断
{
pa=pa->next;
pre=pre->next;
n++;
}
else if(pa->data>pb->data)
{
pb=pb->next;
}
else
{
pre->next=pa->next;
t=pa;
pa=pa->next;
/*
pb=pb->next;*///这个不可以加,由于不确定La中有几个相同的
delete t;
}
}
}
int main()
{
int num1,num2;
int n;//差集的元素个数
while(cin>>num1>>num2&&!(num1==0&&num2==0))
{
n=0;
LinkList L;
LinkList S;
InintList(L);
InintList(S);
LNode *p;
LNode *r;
r=L;
for(int i=1;i<=num1;i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
r=S;
for(int i=1;i<=num2;i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
Difference(L,S,n);
p=L->next;
cout<<p->data;
p=p->next;
while(p)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;
cout<<n<<endl;}
return 0;
}

基于链表的两个集合的交集(标准答案)

2018-10-22

描述
给定两个递增的整数集合A和B,分别用链表表示集合A和B,求出A和B的交集,并存放在A中。要求空间复杂度为O(1)。

输入
多组数据,每组数据有三行,第一行为序列A和B的长度n和m,第二行为序列A的n个元素,第三行为序列B的m个元素(元素之间用空格分隔)。n=0且m=0时输入结束。

输出
对于每组数据输出一行,为A和B的交集,每个数据之间用空格分隔。

样例输入1 复制
5 5
1 3 5 7 9
1 2 3 4 5
3 4
1 2 5
2 4 5 6
0 0
样例输出1
1 3 5
2 5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include<iostream>
#define OK 1
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
bool InintList(LinkList &L)
{
L=new LNode;
L->next=NULL;
return OK;
}
void Intersection(LinkList &La,LinkList &Lb,LinkList &Lc)//求两个递增序列的交集
{
LNode *pa=La->next;
LNode *pb=Lb->next;
LNode *pc;
LNode *t;//暂时指针
Lc=La;
pc=Lc;
while(pa&&pb)
{
if(pa->data==pb->data)
{
pc->next=pa;
pc=pa;
pa=pa->next;
t=pb;
pb=pb->next;
delete t;
}
else if(pa->data<pb->data)
{
t=pa;
pa=pa->next;
delete t;
}
else
{
t=pb;
pb=pb->next;
delete t;
}
}
while(pa)
{
t=pa;
pa=pa->next;
delete t;
}
while(pb)
{
t=pb;
pb=pb->next;
delete t;
}
pc->next=NULL;//不要忘记
delete Lb;
}
int main()
{
int num1,num2;
while(cin>>num1>>num2&&!(num1==0&&num2==0))
{
LinkList L;
LinkList S;
LinkList T;
InintList(L);
InintList(S);
LNode *p;
LNode *r;
r=L;
for(int i=1;i<=num1;i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
r=S;
for(int i=1;i<=num2;i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
Intersection(L,S,T);
p=T->next;
cout<<p->data;
p=p->next;
while(p)
{
cout<<" "<<p->data;
p=p->next;
}
cout<<endl;}
return 0;
}