一.链表学习
一:链表是什么
1、链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,有一系列结点(地址)组成,结点可动态的生成。
2、结点包括两个部分:(1)存储数据元素的数据域(内存空间),(2)存储指向下一个结点地址的指针域。
3、相对于线性表顺序结构,操作复杂。
4.链表分为 (1)单链表 (2)双链表 (3)单向循环链表 (4)双向循环链表
早上第一节物理课确实学不会,就索性打开电脑开始AC链表。
因为太久没有使用链表,所以早上在做链表删重时花多了一点时间来完成。
题目如下
题目描述
有两个链表a和b,从a、b中删除它两重复的元素(只要重复就删除),并对删除后的a链表进行升序排序,b链表进行降序排序。a 的长度为m,b 的长度为n
输入格式
输入a,b的长度m,n
a、b链表
输出格式
处理后的a、b链表
样例输入content_copy
9
6
1 2 3 4 5 6 7 8 6
5 6 7 10 0 5
样例输出content_copy
1 2 3 4 8
10 0
提示/说明
本题是多组输入。
代码如下
#include<stdio.h>
#include<malloc.h>
#define NEW (struct Node*)malloc(sizeof(struct Node))
typedef struct Node{
int data;
struct Node * next;
}NODE,*PNODE;
PNODE build(int num)
{
PNODE head=NULL;
PNODE p1=head;
PNODE p2=NULL;
int data;
for(int i=0;i<num;i++)
{
scanf("%d",&data);
if(head==NULL){head=NEW;p1=head;head->data=data;}
else{p2=NEW;p1->next=p2;p2->data=data;p1=p2;p1->next=NULL;}
}
p2=NEW;
p2->next=head;
head=p2;
head->data=-1;
return head;
}
int dele(PNODE head,int num)
{
PNODE prep=head;
PNODE p=head->next;
int flag=0;
while(p!=NULL)
{
while(p!=NULL&&p->data==num){prep->next=p->next;p=prep->next;flag=1;}
if(p!=NULL){prep=p;p=p->next;}
}
return flag;
}
void judge(PNODE headm,PNODE headn)
{
for(PNODE p=headm->next,prep=headm;p!=NULL;prep=p,p=p->next)
{
if((dele(p,p->data)+dele(headn,p->data))>0) {prep->next=p->next;p=prep;}
}
for(PNODE p=headn->next;p!=NULL;p=p->next)
{
dele(headm,p->data);
dele(p,p->data);
}
}
void PRINT(PNODE head)
{
for(PNODE p=head->next;p!=NULL;p=p->next)
{
printf("%d ",p->data);
}
printf("\n");
}
int main()
{
int m,n;
PNODE headm;
PNODE headn;
while(~scanf("%d%d",&m,&n))
{
headm=build(m);
headn=build(n);
judge(headm,headn);
PRINT(headm);
PRINT(headn);
}
}
因为晚上选修课考试,八点三十回寝室才开始学习到十点半,一共做了两道题目
第一题题目如下:
1518: 最快合并链表(线性表)
时间限制:1s
内存限制:128MB
题目描述
知L1、L2分别为两循环单链表的头结点指针,m,n分别为L1、L2表中数据结点个数。要求设计一算法,用最快速度将两表合并成一个带头结点的循环单链表。
输入格式
m=5
3 6 1 3 5
n=4
7 10 8 4
输出格式
3 6 1 3 5 7 10 8 4
样例输入content_copy
m=7
3 5 1 3 4 6 0
n=5
5 4 8 9 5
样例输出content_copy
3 5 1 3 4 6 0 5 4 8 9 5
结题思路:直接将第一个链表尾链接到第二个链表的第一个节点上就可以(此题因为两个getchar();的问题耗费了过多时间)
#include<bits/stdc++.h>
using namespace std;
#define New (struct node*)malloc(sizeof(struct node))
typedef struct node
{
int data;
node *next;
}node;
int n,m;
node *creat(int num)
{
node* head=NULL;
node* p1=head;
node* p2=NULL;
int data;
for(int i=0;i<num;i++)
{
scanf("%d",&data);
if(head==NULL){head=New;p1=head;head->data=data;}
else{p2=New;p1->next=p2;p2->data=data;p1=p2;p1->next=NULL;}
}
p2=New;
p2->next=head;
head=p2;
head->data=-1;
return head;
}
int main()
{
int i;
node *heada=NULL,*headb=NULL;
scanf("m=%d",&m);
heada=creat(m);//创建A链表
getchar();
getchar();//这两个getchar我真的是查了半个多小时bug才查不来的
scanf("n=%d",&n);
headb=creat(n);//创建B链表
node *p1;
p1=heada->next;
while(p1->next)p1=p1->next;
p1->next=headb->next;
p1=heada->next;
while(p1)
{
printf("%d ",p1->data);
p1=p1->next;
}
}
第二题题目如下:
题目描述
(线性表)已知不带头结点的线性链表list,链表中结点构造为(data、link),其中data为数据域,link为指针域。请写一算法,将该链表按结点数据域的值的大小从小到大重新链接。要求链接过程中不得使用除该链表以外的任何链结点空间。
输入格式
自定义链表节点数
m=5
3 1 5 4 6
输出格式
1 3 4 5 6
样例输入content_copy
8
10 1 5 14 32 55 67 6
样例输出content_copy
1 5 6 10 14 32 55 67
解题思路:和其他排序题思路差不多,只是需要非常注意链表指针指向的问题。
#include<bits/stdc++.h>
using namespace std;
#define New (struct node*)malloc(sizeof(struct node))
typedef struct node
{
int data;
node *next;
}node;
node *creat(int num)//使用尾插法创建链表
{
node* head=NULL,*p1=head,*p2=NULL;
int data;
for(int i=0;i<num;i++)
{
scanf("%d",&data);
if(head==NULL){head=New;p1=head;head->data=data;}
else{p2=New;p1->next=p2;p2->data=data;p1=p2;p1->next=NULL;}
}
return head;
}
node *sortlist(node *h)
{
node *h1,*p,*q,*qm,*pm,*t;
h1=NULL;
while(h)
{
for(pm=q=h,p=h->next;p;q=p,p=p->next)//每次找出链表中的最大值,qm记下最大值的前一个,pm记下最大值
if(p->data>pm->data)
{
qm=q;
pm=p;
}
if(pm!=h)//若最大值不是第一个,就将最大值的节点从链表中分离出来
qm->next=pm->next;
else
h=h->next;
pm->next=h1;//每次找出来的最大值用头插法实现升序
h1=pm;//h1始终指向升序链表的第一个节点
}
return h1;
}
void outlist(node *h)//输出链表
{
while(h)
{
printf("%d ",h->data);
h=h->next;
}
}
int main()
{
int m;
scanf("%d",&m);
node *head=creat(m);
head=sortlist(head);
outlist(head);
}
通过今天的学习,我对于链表的操作稍微熟练了一点点