数据结构与算法A实验二链表
7 - 1 单链表的创建及遍历
#include<bits/stdc++.h>
using namespace std;
struct node{ // 定义节点结构体
int data; // 值
node *next; // 指向下一个节点的索引
};
node *build(node *head,int n){ // 建立链表
head=new node;
node *tail,*p;
head->next=NULL;
tail=head;
for(int i=1;i<=n;i++){ // 输入链表的值
p=new node;
cin>>p->data;
p->next=tail->next;
tail->next=p;
tail=p;
}
return head;
}
void show(node *head){ // 输出列表
node *p=head->next;
while(p){ // 节点不为空
if(p->next) cout<<p->data<<" "; // 最后一个节点输出换行
else cout<<p->data<<endl; // 不是最后一个节点输出空格
p=p->next; // 指针移动到下一个节点
}
}
void solve(){
int n;
cin>>n;
node *head=new node; // 定义链表
head=build(head,n); // 建立链表
show(head); // 输出链表head
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 2 两个有序链表序列的合并
#include<bits/stdc++.h>
using namespace std;
struct node{ // 定义节点结构体
int data; // 值
node *next; // 指向下一个节点的索引
};
node *build(node *head){ // 建立链表
head=new node;
node *tail,*p;
head->next=NULL;
tail=head;
int k;
while(cin>>k&&k!=-1){ // 输入链表的值
p=new node;
p->data=k;
p->next=tail->next;
tail->next=p;
tail=p;
}
return head;
}
node *Merge(node *h1,node *h2){ // 合并链表
node *t1=h1->next,*t2=h2->next;
node *p,*tail;
node *head=new node;
head->next=NULL;
tail=head;
while(t1&&t2){
if(t1->data<t2->data){ // 如果t1值小合并到head中
p=new node;
p->data=t1->data;
p->next=tail->next;
tail->next=p;
tail=p;
t1=t1->next;
}else{ // 如果t2值小合并到head中
p=new node;
p->data=t2->data;
p->next=tail->next;
tail->next=p;
tail=p;
t2=t2->next;
}
}
if(t1) tail->next=t1; // 如果h1链表有剩余 把剩余的放入
if(t2) tail->next=t2; // 如果h2链表有剩余 把剩余的放入
return head;
}
void show(node *head){ // 输出列表
node *p=head->next;
while(p){ // 节点不为空
if(p->next) cout<<p->data<<" "; // 最后一个节点输出换行
else cout<<p->data<<endl; // 不是最后一个节点输出空格
p=p->next; // 指针移动到下一个节点
}
}
void solve(){
node *head1=new node; // 定义链表一
node *head2=new node; // 定义链表二
head1=build(head1); // 建立链表一
head2=build(head2); // 建立链表二
//show(head1);
//show(head2);
node *head=Merge(head1,head2); // 合并链表一、二
if(head->next) show(head); // 如果链表不为空 输出链表head
else cout<<"NULL"<<endl; // 如果链表为空 输出 NULL
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 3 单链表的创建,遍历与销毁
#include<bits/stdc++.h>
using namespace std;
struct node{ // 定义节点结构体
int data; // 值
node *next; // 指向下一个节点的索引
};
node *build(node *head){ // 逆序建立链表
head=new node;
node *tail,*p;
head->next=NULL;
tail=head;
int k;
while(cin>>k&&k!=-1){ // 输入链表的值
p=new node;
p->data=k;
p->next=head->next;
head->next=p;
}
return head;
}
void show(node *head){ // 输出列表
node *p=head->next;
while(p){ // 节点不为空
cout<<p->data<<" "; // 输出节点
p=p->next; // 指针移动到下一个节点
}
}
void solve(){
node *head=new node; // 定义链表
head=build(head); // 建立链表
show(head); // 输出链表head
free(head); // 释放head
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 4 程序设计综合实践 1.3
法一:链表
#include<bits/stdc++.h>
#define ll long long
const int N = 1e7 + 10;
using namespace std;
int tot; // 记录数据个数
int a[N]; // 记录数据
struct node{ // 定义节点结构体
int data;
node *next;
};
node *head1,*head2; // 定义链表
void Reverse(node *head){ // 链表逆置
node *p,*s;
p=head->next;
head->next=NULL;
while(p){
s=p;
p=p->next;
s->next=head->next;
head->next=s;
}
}
void show(node *head){ // 输出链表
node *p=head->next;
if(!p) cout<<endl; // 如果是空链表输出换行 !!
while(p){
if(p->next) cout<<p->data<<"->";
else cout<<p->data<<endl;;
p=p->next;
}
}
void add(node *head,int x){ // 插入节点函数
node *tail=head;
node *q=head->next;
node *p;
if(!q){ // 如果当前链表没有节点
p=new node;
p->data=x;
p->next=head->next;
head->next=p;
}else{ // 如果当前链表有节点
bool tag=0;
while(q&&!tag){ // 按序插入节点
if(x<=q->data){
tag=1;
p=new node;
p->data=x;
p->next=tail->next;
tail->next=p;
break;
}else{
q=q->next;
tail=tail->next;
}
}
if(!tag){ // 如果是最大的 插入到最后
p=new node;
p->data=x;
p->next=tail->next;
tail->next=p;
}
}
}
void build(node *head1,node *head2){ // 构建链表
head1=new node; head1->next=NULL;
head2=new node; head2->next=NULL;
node *p;
for(int i=1;i<=tot;i++){
if(a[i]>0) add(head1,a[i]); // 如果是正整数
else if(a[i]<0) add(head2,a[i]); // 如果负整数
}
show(head1); show(head2); // 输出链表
Reverse(head1);Reverse(head2); // 链表逆置
show(head1); show(head2); // 输出逆置链表
}
void solve(){
string s;
getline(cin,s);
stringstream ss(s);
while(ss>>s){ // 读入元素并存储
int num=0;
if(s[0]=='-'){
for(int i=1;i<s.size();i++){
num=num*10+s[i]-'0';
}
a[++tot]=-num;
}else{
for(int i=0;i<s.size();i++){
num=num*10+s[i]-'0';
}
a[++tot]=num;
}
}
head1=new node;head1->next=NULL;
head2=new node;head2->next=NULL;
build(head1,head2);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
法二:数组
#include <iostream>
#include <algorithm>
#include<bits/stdc++.h>
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define x first
#define y second
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define eb emplace_back
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int N = 2e5 + 10;
const int M = 111;
int dx[]={-1, 0, 1, 0};
int dy[]={0, 1, 0, -1};
using namespace std;
int a[N],tot;
void show(int l,int r){
if(!l||!r){ // 如果是空输出换行
cout<<endl;
return ;
}
if(l<=r){
for(int i=l;i<=r;i++){
if(i!=l) cout<<"->";
cout<<a[i];
}
cout<<endl;
}else{
for(int i=l;i>=r;i--){
if(i!=l) cout<<"->";
cout<<a[i];
}
cout<<endl;
}
}
inline void solve(){
string s;
getline(cin,s);
stringstream ss(s);
while(ss>>s){ // 将数据存入数组
int num=0;
if(s[0]=='-'){
for(int i=1;i<s.size();i++){
num=num*10+s[i]-'0';
}
a[++tot]=-num;
}else{
for(int i=0;i<s.size();i++){
num=num*10+s[i]-'0';
}
a[++tot]=num;
}
}
sort(a+1,a+1+tot); // 排序
int pos=0;
for(int i=1;i<=tot;i++){ // 找到第一个正数位置
if(a[i]>0){
pos=i;
break;
}
}
// 输出结果
show(pos,tot);
show(1,pos-1);
show(tot,pos);
show(pos-1,1);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 5 程序设计综合实践 1.4
#include<bits/stdc++.h>
#define ll long long
const int N = 1e7 + 10;
using namespace std;
int tot; // 记录数据个数
int a[N]; // 记录数据
struct node{ // 定义节点结构体
int data;
node *next;
};
node *head,*head1,*head2; // 定义链表
void show(node *head){ // 输出链表
node *p=head->next;
if(!p) cout<<endl; // 如果是空链表输出换行 !!
while(p){
if(p->next) cout<<p->data<<"->";
else cout<<p->data<<endl;;
p=p->next;
}
}
void add(node *head,int x){ // 插入节点函数
node *tail=head;
node *q=head->next;
node *p;
if(!q){ // 如果当前链表没有节点
p=new node;
p->data=x;
p->next=head->next;
head->next=p;
}else{ // 如果当前链表有节点
bool tag=0;
while(q&&!tag){ // 按序插入节点
if(x<=q->data){
tag=1;
p=new node;
p->data=x;
p->next=tail->next;
tail->next=p;
break;
}else{
q=q->next;
tail=tail->next;
}
}
if(!tag){ // 如果是最大的 插入到最后
p=new node;
p->data=x;
p->next=tail->next;
tail->next=p;
}
}
}
void build(node *head,node *head1,node *head2){ // 构建链表
head1=new node; head1->next=NULL;
head2=new node; head2->next=NULL;
node *p;
for(int i=1;i<=tot;i++){
add(head,a[i]); // 插入总链表
if(a[i]&1) add(head1,a[i]); // 如果是奇数
else add(head2,a[i]); // 如果是偶数
}
show(head);show(head1); show(head2); // 输出链表
}
void solve(){
string s;
getline(cin,s);
stringstream ss(s);
while(ss>>s){ // 读入元素并存储
int num=0;
if(s[0]=='-'){
for(int i=1;i<s.size();i++){
num=num*10+s[i]-'0';
}
a[++tot]=-num;
}else{
for(int i=0;i<s.size();i++){
num=num*10+s[i]-'0';
}
a[++tot]=num;
}
}
head=new node;head->next=NULL;
head1=new node;head1->next=NULL;
head2=new node;head2->next=NULL;
build(head,head1,head2);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 6 删除重复字符
坑点: 有空格!
#include<bits/stdc++.h>
using namespace std;
set<char>st;
void solve(){
string s;
getline(cin,s);
for(int i=0;i<s.size();i++) st.insert(s[i]);
for(auto i:st) cout<<i;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 7 约瑟夫环
#include<bits/stdc++.h>
#define eb emplace_back
using namespace std;
int n;
struct node{ // 定义节点结构体
int data; // 值
node *next; // 指向下一个节点的索引
};
vector<int>ord;
node *build(node *head){ // 逆序建立链表
head=new node;
node *tail,*p;
head->next=NULL;
head->data=1; // 建立第一个节点
tail=head;
for(int i=2;i<=n;i++){ // 输入链表的值 顺序建链表
p=new node;
p->data=i;
p->next=NULL;
tail->next=p;
tail=p;
}
tail->next=head; // 尾节点和头节点链接 形成循环链表
return head;
}
void Joseph(node *head,int p){ // 按照要求退出
node *tail=head;
for(int i=1;i<n;i++) tail=tail->next; // 找到头节点的前一个节点 便于p=1时的删除
node *q=head;
int tot=n;
int cnt=1;
while(tot>1){ // 删点过程
if(cnt==p){ // 如果报数为p 则删除
ord.eb(q->data); // 存入答案
tot--; // 节点数量减少1
cnt=1; // 从头报数
tail->next=q->next; // 删点
q=tail->next;
}else{ // 没有报到p 则后移
q=q->next;
tail=tail->next;
cnt++;
}
}
ord.eb(q->data); // 放入最后一个节点
}
void solve(){
int p;
cin>>n>>p;
node *head=new node; // 定义链表
head=build(head); // 建立链表
Joseph(head,p); // 按照要求删点
for(int i=0;i<ord.size();i++){ // 输出退出顺序
if(i) cout<<" ";
cout<<ord[i];
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 8 一元多项式的乘法与加法运算
#include<bits/stdc++.h>
#define ll long long
#define eb emplace_back
#define x first
#define y second
const int N = 1e7 + 10;
using namespace std;
map<ll,ll>ind; // 记录加法系数
vector<ll>res; // 记录加法答案
map<ll,ll>ap,bp,cp; // ap 记录第一个方程 bp 表示第二个方程 cp 表示乘法结果
vector<ll>vp; // 记录乘法答案
void show(map<ll,ll>Index,vector<ll>Res){ // 输出函数
for(auto i:Index){ // 遍历指数 去除系数为零的指数
if(i.y){
Res.eb(i.x);
Res.eb(i.y);
}
}
if(Res.size()){ // 如果不是零多项式 倒序输出
for(int i=Res.size()-1;i>=0;i--){
if(i!=Res.size()-1) cout<<" ";
cout<<Res[i];
}
cout<<endl;
}else cout<<"0 0"<<endl; // 如果是零多项式 输出 0 0
}
void solve(){
int n;
cin>>n;
int a,b;
for(int i=1;i<=n;i++){ // 输入第一个表达式
cin>>a>>b;
ind[b]+=a; // 对应指数位置加上系数值
ap[b]+=a;
}
cin>>n;
for(int i=1;i<=n;i++){ // 输入第二个表达式
cin>>a>>b;
ind[b]+=a;
bp[b]+=a;
}
for(auto i:ap){ // 乘法运算
for(auto j:bp){
cp[i.x+j.x]+=i.y*j.y;
}
}
show(cp,vp); // 输出乘法结果
show(ind,res); // 输出加法结果
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 9 带头节点的双向循环链表操作
双向链表: 注意每个节点的pre和next链接
#include<bits/stdc++.h>
#define ll long long
const int N = 1e7 + 10;
using namespace std;
int tot; // 记录数据个数
int a[N]; // 记录数据
struct node{ // 定义节点结构体
int data;
node *pre;
node *next;
};
void show(node *head){ // 输出链表
node *p=head->next;
while(p){
if(p->next) cout<<p->data<<" ";
else cout<<p->data<<endl;;
p=p->next;
}
}
void reshow(node *tail){ // 逆序输出链表
node *p=tail;
while(p->pre){
if(p->pre->pre) cout<<p->data<<" ";
else cout<<p->data<<endl;;
p=p->pre;
}
}
void build(node *head){ // 构建链表
head=new node;
head->pre=NULL;
head->next=NULL;
node *p;
node *tail=head;
node *q=head->next;
for(int i=1;i<=tot;i++){ // 插入节点
q=head->next;
int x=a[i];
if(!q){ // 如果当前链表没有节点
p=new node;
p->data=x;
p->pre=head;
p->next=head->next;
head->next=p;
tail=p;
}else{ // 如果当前链表有节点
if(i&1){
p=new node;
p->data=x;
p->pre=head;
p->next=head->next;
p->next->pre=p;
head->next=p;
}else{
p=new node;
p->data=x;
p->next=NULL;
p->pre=tail;
tail->next=p;
tail=p;
}
}
}
show(head); // 输出链表
reshow(tail); // 输出逆置链表
}
void solve(){
int x;
while(cin>>x&&x!=-1) a[++tot]=x;
node *head=new node;
head->next=NULL;
build(head);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
单向链表:
#include<bits/stdc++.h>
#define ll long long
const int N = 1e7 + 10;
using namespace std;
int tot; // 记录数据个数
int a[N]; // 记录数据
struct node{ // 定义节点结构体
int data;
node *pre;
node *next;
};
void Reverse(node *head){ // 链表逆置
node *p,*s;
p=head->next;
head->next=NULL;
while(p){
s=p;
p=p->next;
s->next=head->next;
head->next=s;
}
}
void show(node *head){ // 输出链表
node *p=head->next;
while(p){
if(p->next) cout<<p->data<<" ";
else cout<<p->data<<endl;;
p=p->next;
}
}
void build(node *head){ // 构建链表
head=new node;
head->next=NULL;
node *p;
node *tail=head;
node *t=head;
node *q=head->next;
for(int i=1;i<=tot;i++){ // 插入节点
q=head->next;
int x=a[i];
if(!q){ // 如果当前链表没有节点
p=new node;
p->data=x;
p->next=head->next;
head->next=p;
t=p;
}else{ // 如果当前链表有节点
if(i&1){
p=new node;
p->data=x;
p->next=head->next;
head->next=p;
}else{
p=new node;
p->data=x;
p->next=NULL;
t->next=p;
t=p;
}
}
}
show(head); // 输出链表
Reverse(head); // 链表逆置
show(head); // 输出逆置链表
}
void solve(){
int x;
while(cin>>x&&x!=-1) a[++tot]=x;
node *head=new node;
head->next=NULL;
build(head);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}
7 - 10 链表去重
#include <iostream>
#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define ll long long
#define INF 0x3f3f3f3f
const int N = 1e5 + 10;
using namespace std;
struct node{
int add;
int key;
int next;
int num;
} dp[N];
bool vis[N];
bool cmp(node x,node y){
return x.num<y.num;
}
int main(){
ios::sync_with_stdio(0);
int head;
int n;
cin>>head>>n;
int i;
int k1=0;
int k2=0;
for(i=0; i<N; i++)dp[i].num=2*N;
int k;
for(i=0; i<n; i++){
cin>>k;
cin>>dp[k].key>>dp[k].next;
dp[k].add=k;
}
for(i=head; i!=-1; i=dp[i].next){
if(!vis[abs(dp[i].key)]){
vis[abs(dp[i].key)]=1;
dp[i].num=k1;
k1++;
}else{
dp[i].num=N+k2;
k2++;
}
}
sort(dp,dp+N,cmp);
int cnt=k1+k2;
for(i=0; i<cnt; i++){
if(i!=k1-1&&i!=cnt-1) printf("%05d %d %05d\n",dp[i].add,dp[i].key,dp[i+1].add);
else printf("%05d %d -1\n",dp[i].add,dp[i].key);
}
return 0;
}
7 - 11 单链表就地逆置
#include<bits/stdc++.h>
using namespace std;
struct node{ // 定义节点结构体
int data; // 值
node *next; // 指向下一个节点的索引
};
node *build(node *head){ // 逆序建立链表
head=new node;
node *tail,*p;
head->next=NULL;
tail=head;
int k;
while(cin>>k&&k!=-1){ // 输入链表的值
p=new node;
p->data=k;
p->next=head->next;
head->next=p;
}
return head;
}
void show(node *head){ // 输出列表
node *p=head->next;
while(p){ // 节点不为空
if(p->next) cout<<p->data<<" "; // 最后一个节点输出换行
else cout<<p->data<<endl; // 不是最后一个节点输出空格
p=p->next; // 指针移动到下一个节点
}
}
void solve(){
node *head=new node; // 定义链表
head=build(head); // 建立链表
show(head); // 输出链表head
free(head); // 释放head
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--) solve();
return 0;
}