1.创建链表
(1)【基本要求】
从键盘输入一组整数,创建单向链表,并输出链表中的数据。
样例输入:2 5 7 6 3 4
样例输出:2 5 7 6 3 4
(2)【功能实现】
#include<stdio.h>
#include<stdlib.h>
#define N 4 /*链表的长度*/
struct Node //链表结点的结构体
{
int data; //结点的值
struct Node *next; //指向下一个结点的指针
};
//创建n个结点的链表,返回链表的首结点地址
Node* createList(int n);
//输出头结点地址为first的链表
void printList(Node *first);
//释放头结点地址为first的链表所有结点占据的内存空间
void destoryList(Node *first);
int main()
{
Node *list;
printf("请输入%d个数以建立链表\n",N);
//创建N个结点的链表,链表首结点地址=>list
list=createList(N);
printList(list); //输出头结点地址为list链表
destoryList(list); //释放头结点地址为list的链表所有结点占据的内存空间
printf("\n");
}
//创建n个结点的链表,返回链表的首结点地址
Node* createList(int n)
{ /*尾插法建立链表*/
//first:指向首结点,last:指向最后一个结点,t指向临时结点
Node *t,*first,*last;
int i;
//分配一个结点的空间 => 第1个结点
first=(Node *)malloc(sizeof(Node));
scanf("%d",&first->data); //输入第一个结点的值
last=first; //只有一个结点,既是队首也是队尾
//创建其余的n-1个结点
for(i=n-1;i>0;i--)
{
//分配一个结点的空间 => 临时结点t
t=(Node *)malloc(sizeof(Node));
scanf("%d",&t->data); //输入下一个结点的值
last->next=t; //将临时结点t插入到链表的尾部
last=t; //临时结点t变成链表的尾部
}
last->next=NULL; //队尾结点的下一个结点为空
return first;
}
/*遍历链表并输出*/
void printList(Node *first)
{
Node *p=first;
while(p!=NULL)
{
printf("%3d",p->data);
p=p->next;
}
printf("\n");
}
//释放头结点地址为first的链表所有结点占据的内存空间
//free(p)释放指针p指向的结点占据的内存空间
//free函数,在stdlib.h头文件中定义
void destoryList(Node *first)
{
Node *p=first,*temp;
while(p!=NULL)
{
//使用过多少次malloc函数分配内存,就要使用多少次free函数释放内存
temp=p->next; //暂存下一个结点的地址
free(p); //释放当前结点的内存空间
p=temp; // p指向下一个结点
}
}
(3)【运行结果】
2.链表合并
(1)【基本要求】
从键盘输入两组由小到大的整数,每组数据创建一个链表。然后将两个链表合并,合并后的链表仍然保持由小到大的顺序。最后输出合并后的链表。
样例输入:
1 2 5 7
2 3 6 8 9
样例输出:1 2 2 3 5 6 7 8 9
(2)【功能实现】
代码一:
#include<stdio.h>
#include<stdlib.h>
#define N1 4 //链表La的长度
#define N2 5 //链表Lb的长度
struct Node{
int data;
struct Node *next;
};
Node* createList(int n);
Node* mergeList(Node *la,Node *lb);//两个有序链表合并,返回合并后链表的首结点地址
void printList(Node *p);
void destoryList(Node *first);
int main(){
Node *la,*lb;
printf("请按照升序,输入%d个数以建立链表La\n",N1);
//创建N1个结点的链表,链表首结点地址=>la
la=createList(N1);
printf("请按照升序,输入%d个数以建立链表Lb\n",N2);
//创建N2个结点的链表,链表首结点地址=>lb
lb=createList(N2);
la=mergeList(la,lb);//合并两链表=>la
printList(la);//输出链表la
destoryList(la);//释放合并后的链表所有结点占据的内存空间
printf("\n");
}
Node* createList(int n){
Node *t,*first,*last;
int i;
first=(Node *)malloc(sizeof(Node));
scanf("%d",&first->data);
last=first;
for(i=n-1;i>0;i--)
{
t=(Node *)malloc(sizeof(Node));
scanf("%d",&t->data);
last->next=t;
last=t;
}
last->next=NULL;
return first;
}
Node* mergeList(Node *la,Node *lb){
Node *first=NULL;
Node *last=NULL;
while(la&&lb) {
if(la->data<lb->data)
{
if(first==NULL)
{
first=la;
last=la;
}
else
{
last->next=la;
last=la;
}
la=la->next;
}
else if (la->data>lb->data)
{
if(first==NULL)
{
first=lb;
last=lb;
}
else
{
last->next=lb;
last=lb;
}
lb=lb->next;
}
else
{
if(first==NULL)
{
first=la;
last=la;
}
else {
last->next=la;
last=la;
}
la=la->next;
last->next=lb;
last=lb;
lb=lb->next;
}
}
if(la) // la≠0
last->next=la;
if(lb) // lb≠0
last->next=lb;
return first;
}
void printList(Node *first)
{
Node *p=first;
while(p!=NULL){
printf("%3d",p->data);
p=p->next;
}
printf("\n");
}
void destoryList(Node *first)
{
Node *p=first,*temp;
while(p!=NULL){
temp=p->next;
free(p);
p=temp;
}
}
代码二:
#include<stdio.h>
#include<stdlib.h>
#define N1 4 /*链表La的长度*/
#define N2 5 /*链表Lb的长度*/
struct Node //链表的结点
{
int data;
struct Node *next;
};
Node* createList(int n);
/*将结点t连接到last指向的结点后面
在函数中,由于first、last的值可能被修改, 还需要带回到调用的函数,
所以实参是fisrt、last的地址
firstPoint=&first
lastPoint=&last */
void append(Node **firstPoint,Node **lastPoint,Node *t);
//两个有序链表合并,返回合并后链表的首结点地址
Node* mergeList(Node *la,Node *lb);
//打印链表
void printList(Node *p);
//释放头结点地址为first的链表所有结点占据的内存空间
void destoryList(Node *first);
int main()
{
Node *la,*lb;
printf("请按照升序,输入%d个数以建立链表La\n",N1);
//创建N1个结点的链表,链表首结点地址=>la
la=createList(N1);
printf("请按照升序,输入%d个数以建立链表Lb\n",N2);
//创建N2个结点的链表,链表首结点地址=>lb
lb=createList(N2);
la=mergeList(la,lb); //合并两链表=>la
printList(la); //输出链表la
destoryList(la); //释放合并后的链表所有结点占据的内存空间
printf("\n");
}
//创建n个结点的链表,返回链表的首结点地址
Node* createList(int n)
{ /*尾插法建立链表*/
Node *t,*first,*last;
int i;
//分配一个结点的空间 => 第1个结点
first=(Node *)malloc(sizeof(Node));
scanf("%d",&first->data); //输入第一个结点的值
last=first; //只有一个结点,既是链表的首部也是链表的尾部
//创建其余的n-1个结点
for(i=n-1;i>0;i--)
{
//分配一个结点的空间 => 临时结点t
t=(Node *)malloc(sizeof(Node));
scanf("%d",&t->data); //输入下一个结点的值
last->next=t; //将临时结点t插入到链表的尾部
last=t; //临时结点t变成链表的尾部
}
last->next=NULL; //链表的尾部结点的下一个结点为空
return first;
}
//将结点t接到首结点地址为*firstPoint,尾结点地址为 *lastPoint 的链表的尾部
void append(Node **firstPoint,Node **lastPoint,Node *t)
{
if(*firstPoint==NULL) //合并后的链表为空
//结点t既作为合并后的头结点
*firstPoint=t;
else //合并后的链表不为空
//将结点t插入到合并后链表的尾部
(*lastPoint)->next=t;
*lastPoint=t;//t变成并后链表的最后一个结点
}
//两个链表合并,返回合并后链表的首结点地址
Node* mergeList(Node *la,Node *lb)
{ /*将两个链表按递增序列排序*/
Node *first=NULL; //合并后链表的首结点地址
Node *last=NULL; //合并后链表的尾结点地址
//链表la和链表lb都不为空(都没有到最后)
while(la&&lb)
{
//链表la当前结点的值<链表lb当前结点的值
if(la->data<lb->data)
{
//将la的第1个结点,连到last的后面
append(&first,&last,la);
la=la->next; //链表la指针移向下一个结点
}
else if (la->data>lb->data) //链表la当前结点的值>链表lb当前结点的值
{
//将lb的第1个结点,连到last的后面
append(&first,&last,lb);
lb=lb->next; //链表lb指针移向下一个结点
}
else //链表la当前结点的值=链表lb当前结点的值
{
//将la的第1个结点,连到last的后面
append(&first,&last,la);
la=la->next; //链表la指针移向下一个结点
//将lb的第1个结点,连到last的后面
append(&first,&last,lb);
lb=lb->next; //链表lb指针移向下一个结点
}
}
//链表la不为空,链表lb为空
if(la) // la≠0
last->next=la;
//链表lb不为空,链表la为空
if(lb) // lb≠0
last->next=lb;
return first;
}
/*遍历链表并输出*/
void printList(Node *first)
{
Node *p=first;
while(p!=NULL)
{
printf("%3d",p->data);
p=p->next;
}
printf("\n");
}
//释放头结点地址为first的链表所有结点占据的内存空间
//free(p)释放指针p指向的结点占据的内存空间
//free函数,在stdlib.h头文件中定义
void destoryList(Node *first)
{
Node *p=first,*temp;
while(p!=NULL)
{
//使用过多少次malloc函数分配内存,就要使用多少次free函数释放内存
temp=p->next; //暂存下一个结点的地址
free(p); //释放当前结点的内存空间
p=temp; // p指向下一个结点
}
}
(3)【运行结果】