第1关:单链表的插入操作

任务描述

本关任务:编写单链表的初始化、插入、遍历三个操作函数。

测试说明

平台会对你编写的代码进行测试:

测试输入:
5
12 47 5 8 69
1
99
预期输出:
插入成功,插入后单链表如下:
99 12 47 5 8 69

测试输入:
5
12 47 5 8 69
7
99
预期输出:
插入位置不合法,插入失败!

输入说明
第一行输入单链表的数据元素的个数M;
第二行输入单链表M个整数;
第三行输入要插入元素的位置;
第四行输入要插入的数据元素的值。

输出说明
第一行输出插入是否成功的提示信息;
如果插入成功,第二行输出插入元素后的单链表所有元素;如果插入失败,则不输出第二行。

代码如下

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

/* 定义ElemType为int类型 */
typedef int ElemType;
void input(ElemType &s);
void output(ElemType s);
int equals(ElemType a,ElemType b);
/* 单链表类型定义 */
typedef struct LNode
{	
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;

void InitList(LinkList &L);
int ListInsert(LinkList L,int i,int e) ;
void ListTraverse(LinkList L,void(*vi)(ElemType));

int main()               //main() function 
{	
     LinkList A;
     ElemType e;
     InitList(A);
      int n,i;
     // cout<<"Please input the list number ";
     cin>>n;
     for(i=1;i<=n;i++)
        { 
		   cin>>e;
         ListInsert(A, i, e);
       }
	//cout<<"请输入插入的位置:"<<endl;
	cin>>i;
	//cout<<"请输入插入的值:"<<endl;
	input(e);
	if(  ListInsert(A,i,e) )
    {
      cout<<"插入成功,插入后单链表如下:"<<endl;
      ListTraverse(A,output) ;
    }
    else
    	cout<<"插入位置不合法,插入失败!"<<endl;
    return  0;  
 }


/*****ElemType类型元素的基本操作*****/
void input(ElemType &s)
{
cin>>s;
}
void output(ElemType s)
 {
cout<<s<<" ";
}
int equals(ElemType a,ElemType b)
{
	if(a==b)
		return  1;
	else
		return  0;
}

/*****单链表的基本操作*****/
void InitList(LinkList &L)
{ 
	// 操作结果:构造一个空的单链表L
	/********** Begin **********/ 
	L=(LinkList)malloc(sizeof(LNode));
	if(!L) exit(-1);
	L->next=NULL;
	/********** End **********/
}
int ListInsert(LinkList L,int i,int e) 
{
	// 在带头结点的单链线性表L的第i个元素之前插入元素e  
	/********** Begin **********/ 
	int j=0;
	LinkList p=L,s;
	while(p!=NULL && j<i-1){
		p=p->next;
		j++;
	}
	if(!p || j>i-1) return 0;
	s=(LinkList)malloc(sizeof(LNode));
	s->data=e;
	s->next=p->next;
	p->next=s;
	return 1;
	/********** End **********/
}

void ListTraverse(LinkList L,void(*vi)(ElemType))
{ 
	// 初始条件:单链表L已存在。
	//操作结果:依次对L的每个数据元素调用函数vi()
	/********** Begin **********/ 
	LinkList p=L->next;
	while(p){
		vi(p->data);
		p=p->next;
	}
	printf("\n");
	/********** End **********/
}

第2关:单链表的删除操作

任务描述

本关任务:编写单链表的删除操作函数。

测试说明

平台会对你编写的代码进行测试:

测试输入:
5
12 47 5 8 69
1
预期输出:
删除成功,删除后单链表如下:
47 5 8 69
删除元素的值:12

测试输入:
5
12 47 5 8 69
6
预期输出:
删除位置不合法,删除失败!

输入说明
第一行输入单链表的长度M;
第二行输入单链表的M个整数;
第三行输入要删除元素的位置;

输出说明
第一行输出删除是否成功的提示信息;
如果删除成功,第二行输出删除元素后的单链表;第三行输出删除的数据元素;如果删除位置不合法,不输出第二行和第三行。

代码如下

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

/* 定义ElemType为int类型 */
typedef int ElemType;
void input(ElemType &s);
void output(ElemType s);
int equals(ElemType a,ElemType b);

/* 单链表类型定义 */
typedef struct LNnode
{	
	ElemType data;
	struct LNnode *next;
}LNnode,*LinkList;

void InitList(LinkList &L);
int ListInsert(LinkList &L,int i,int e) ;
int ListDelete(LinkList L,int i,ElemType &e);
void ListTraverse(LinkList L,void(*vi)(ElemType));

int main()               //main() function 
{	
	LinkList A;
	ElemType e;
	InitList(A);
	int n,i;
	// cout<<"Please input the list number ";
	cin>>n;
	for(i=1;i<=n;i++)
	{ 
		cin>>e;
		ListInsert(A, i, e);
	}
	//cout<<"请输入删除的位置:"<<endl;
	cin>>i;	
	if(  ListDelete(A,i,e) )
	{
		cout<<"删除成功,删除后单链表如下:"<<endl;
		ListTraverse(A,output) ;
		cout<<"删除元素的值:";
	   output(e);
   	   cout<<endl;
	}
	else
		cout<<"删除位置不合法,删除失败!"<<endl;
}



/*****ElemType类型元素的基本操作*****/
void input(ElemType &s)
{
	cin>>s;
}
void output(ElemType s)
{
	cout<<s<<" ";
}
int equals(ElemType a,ElemType b)
{
	if(a==b)
		return  1;
	else
		return  0;
}

/*****单链表的基本操作*****/
void InitList(LinkList &L)
{ 	// 构造一个空的单链表L	
	L=(LinkList)malloc(sizeof(LNnode)); // 产生头结点,并使L指向此头结点
	if(!L) // 存储分配失败
		return ;
	L->next=NULL; // 指针域为空
	
}

int ListInsert(LinkList &L,int i,ElemType e) 
{	// 在带头结点的单链线性表L的第i个元素之前插入元素e  
	LinkList p,s;
	p = L;   
	int j = 0;
	while (p && j < i-1) {  // 寻找第i-1个结点
		p = p->next;
		++j;
	} 
	if (!p || j > i-1) 
		return 0;                   // i小于1或者大于表长
	s = (LinkList)malloc(sizeof(LNnode));  // 生成新结点
	s->data = e;  s->next = p->next;      // 插入L中
	p->next = s;
	return 1;
}

void ListTraverse(LinkList L,void(*vi)(ElemType))
{ 	// 调用函数vi()依次输出单链表L的每个数据元素
	LinkList p=L->next;
	while(p)
	{
		vi(p->data);
		p=p->next;
	}
	printf("\n");	
}

int  ListDelete(LinkList L,int i,ElemType &e) // 算法2.10。不改变L
{ 
	// 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值
	/********** Begin **********/ 
	int j=0;LinkList p=L,r;
	while(p->next && j<i-1){
		p=p->next;
		j++;
	}
	if(!p->next || j>i-1) return 0;
	r=p->next;
	p->next=r->next;
	e=r->data;
	free(r);
	return 1;
	/********** End **********/
}

第3关:单链表的按照序号查找值操作

任务描述

本关任务:编写单链表按照序号i查找数据元素值操作函数。

测试说明

平台会对你编写的代码进行测试:

测试输入:
10
12 47 5 8 6 92 45 63 75 38
8

预期输出:
查找成功!
第8个元素的值:
63

测试输入:
10
12 47 5 8 6 92 45 63 75 38
11

预期输出:
查找失败!

输入说明
第一行输入单链表的长度M;
第二行输入单链表的M个整数;
第三行输入要查找的序号。

输出说明
第一行输出按照序号查找是否成功的提示信息;
如果查找成功,输出查找的数据元素的值;如果查找失败,则不输出。

代码如下

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

/* 定义ElemType为int类型 */
typedef int ElemType;
void input(ElemType &s);
void output(ElemType s);
int equals(ElemType a,ElemType b);

/* 单链表类型定义 */
typedef struct LNnode
{	
	ElemType data;
	struct LNnode *next;
}LNnode,*LinkList;

void InitList(LinkList &L);
int ListInsert(LinkList &L,int i,int e) ;
void ListTraverse(LinkList L,void(*vi)(ElemType));
int GetElem(LinkList L,int i,ElemType &e) ;

int main()               //main() function 
{	
	LinkList A;
	ElemType e;
	InitList(A);
	int n,i;
	// cout<<"Please input the list number ";
	cin>>n;
	for(i=1;i<=n;i++)
	{ 
		cin>>e;
		ListInsert(A, i, e);
	}
	//cout<<"请输入查找的序号:"<<endl;
	cin>>i;	
	if(  GetElem(A,i,e) )
	{
		cout<<"查找成功!"<<endl;
		cout<<"第"<<i<<"个元素的值:"<<endl;
	    output(e);
        cout<<endl;
	}
	else
		cout<<"查找失败!"<<endl;
}

/*****ElemType类型元素的基本操作*****/
void input(ElemType &s)
{
	cin>>s;
}
void output(ElemType s)
{
	cout<<s<<" ";
}
int equals(ElemType a,ElemType b)
{
	if(a==b)
		return  1;
	else
		return  0;
}

/*****单链表的基本操作*****/
void InitList(LinkList &L)
{ 	// 操作结果:构造一个空的单链表L
	L=(LinkList)malloc(sizeof(LNnode)); // 产生头结点,并使L指向此头结点
	if(!L) // 存储分配失败
		return ;
	L->next=NULL; // 指针域为空
	
}

int ListInsert(LinkList &L,int i,ElemType e) 
{	// 在带头结点的单链线性表L的第i个元素之前插入元素e  
	LinkList p,s;
	p = L;   
	int j = 0;
	while (p && j < i-1) {  // 寻找第i-1个结点
		p = p->next;
		++j;
	} 
	if (!p || j > i-1) 
		return 0;                   // i小于1或者大于表长
	s = (LinkList)malloc(sizeof(LNnode));  // 生成新结点
	s->data = e;  s->next = p->next;      // 插入L中
	p->next = s;
	return 1;
}

void ListTraverse(LinkList L,void(*vi)(ElemType))
{ 	// 初始条件:单链表L已存在。
	//操作结果:依次对L的每个数据元素调用函数vi()
	LinkList p=L->next;
	while(p)
	{
		vi(p->data);
		p=p->next;
	}
	printf("\n");
}

int GetElem(LinkList L,int i,ElemType &e) 
{ 
	// L为带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回1,否则返回0
	/********** Begin **********/ 
	int j=1;
	LinkList p=L->next;
	while(p && j<i){
		p=p->next;
		j++;
	}
	if(!p || j>i) return 0;
	e=p->data;
	return 1;  
	/********** End **********/
}

第4关:单链表的按照值查找结点位序的操作

任务描述

本关任务:编写单链表的按照值查找结点位序的操作函数。

测试说明

平台会对你编写的代码进行测试:

测试输入:
10
12 47 5 8 6 92 45 63 75 38
92

预期输出:
查找成功!
92 是单链表第6个元素

测试输入:
10
12 47 5 8 6 92 45 63 75 38
93

预期输出:
查找失败!

输入说明
第一行输入单链表的长度M;
第二行输入单链表的M个整数;
第三行输入要查找的数据元素的值。

输出说明
第一行输出按照值查找是否成功的提示信息;
如果查找成功,第二行输出查找元素的逻辑序号;如果查找失败,则不输出。

代码如下

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;


/* 定义ElemType为int类型 */
typedef int ElemType;
void input(ElemType &s);
void output(ElemType s);
int equals(ElemType a,ElemType b);

/* 单链表类型定义 */
typedef struct LNnode
{	
	ElemType data;
	struct LNnode *next;
}LNnode,*LinkList;
void InitList(LinkList &L);
int ListInsert(LinkList &L,int i,int e) ;
void ListTraverse(LinkList L,void(*vi)(ElemType));
int LocateElem(LinkList L,ElemType e,int(*compare)(ElemType,ElemType));
int main()               //main() function 
{	
	LinkList A;
	ElemType e;
	InitList(A);
	int n,i;
	// cout<<"Please input the list number ";
	cin>>n;
	for(i=1;i<=n;i++)
	{ 
		cin>>e;
		ListInsert(A, i, e);
	}
	//cout<<"请输入查找的元素:"<<endl;
	cin>>e;	
	i=LocateElem(A,e,equals);
	if( i ) 
	{
		cout<<"查找成功!"<<endl;		
	    output(e);
      cout<<"是单链表第"<<i<<"个元素"<<endl;
	}
	else
		cout<<"查找失败!"<<endl;
}



/*****ElemType类型元素的基本操作*****/
void input(ElemType &s)
{
	cin>>s;
}
void output(ElemType s)
{
	cout<<s<<" ";
}
int equals(ElemType a,ElemType b)
{
	if(a==b)
		return  1;
	else
		return  0;
}

/*****单链表的基本操作*****/
void InitList(LinkList &L)
{ 	// 操作结果:构造一个空的单链表L
	L=(LinkList)malloc(sizeof(LNnode)); // 产生头结点,并使L指向此头结点
	if(!L) // 存储分配失败
		return ;
	L->next=NULL; // 指针域为空	
}

int ListInsert(LinkList &L,int i,ElemType e) 
{	// 在带头结点的单链线性表L的第i个元素之前插入元素e  
	LinkList p,s;
	p = L;   
	int j = 0;
	while (p && j < i-1) {  // 寻找第i-1个结点
		p = p->next;
		++j;
	} 
	if (!p || j > i-1) 
		return 0;                   // i小于1或者大于表长
	s = (LinkList)malloc(sizeof(LNnode));  // 生成新结点
	s->data = e; 
    s->next = p->next;      // 插入L中
	p->next = s;
	return 1;	
}

void ListTraverse(LinkList L,void(*vi)(ElemType))
{ 	// 初始条件:单链表L已存在。
	//操作结果:依次对L的每个数据元素调用函数vi()
	LinkList p=L->next;
	while(p)
	{
		vi(p->data);
		p=p->next;
	}
	printf("\n");
}

int LocateElem(LinkList L,ElemType e,int (*equal)(ElemType,ElemType))
{ 
	// 初始条件: 单链表L已存在,equal()是数据元素判定函数(满足为1,否则为0)
	// 操作结果: 返回L中第1个与e满足关系equal()的数据元素的位序,若这样的数据元素不存在,则返回值为0
	/********** Begin **********/ 
	int i=0;
	LinkList p=L->next;
	while(p){
		i++;
		if(equal(p->data,e)) return i;
		p=p->next;
	}
	return 0;
	/********** End **********/
}

第5关:单链表的逆置操作

任务描述

本关任务:编写单链表的逆置操作函数。

测试说明

平台会对你编写的代码进行测试:

测试输入:
10
12 47 5 8 6 92 45 63 75 38

预期输出:
逆置单链表:
38 75 63 45 92 6 8 5 47 12

输入说明
第一行输入单链表的长度M;
第二行输入单链表的M个整数;

输出说明
第一行输出提示信息;
第二行输出逆置后的单链表。

代码如下

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

/* 定义ElemType为int类型 */
typedef int ElemType;
void input(ElemType &s);
void output(ElemType s);
int equals(ElemType a,ElemType b);

/* 单链表类型定义 */
typedef struct LNnode
{	
	ElemType data;
	struct LNnode *next;
}LNnode,*LinkList;
void InitList(LinkList &L);
int ListInsert(LinkList &L,int i,int e) ;
void ListTraverse(LinkList L,void(*vi)(ElemType));
void reverse (LinkList &L);
int main()               //main() function 
{	
	LinkList A;
	ElemType e;
	InitList(A);
	int n,i;
	// cout<<"Please input the list number ";
	cin>>n;
	for(i=1;i<=n;i++)
	{ 
		cin>>e;
		ListInsert(A, i, e);
	}
	cout<<"逆置单链表:"<<endl;
	reverse(A);
	ListTraverse(A,output) ;	
}

/*****ElemType类型元素的基本操作*****/
void input(ElemType &s)
{
	cin>>s;
}
void output(ElemType s)
{
	cout<<s<<" ";
}
int equals(ElemType a,ElemType b)
{
	if(a==b)
		return  1;
	else
		return  0;
}

/*****单链表的基本操作*****/
void InitList(LinkList &L)
{ 	// 操作结果:构造一个空的单链表L
	L=(LinkList)malloc(sizeof(LNnode)); // 产生头结点,并使L指向此头结点
	if(!L) // 存储分配失败
		return ;
	L->next=NULL; // 指针域为空	
}

int ListInsert(LinkList &L,int i,ElemType e) 
{	// 在带头结点的单链线性表L的第i个元素之前插入元素e  
	LinkList p,s;
	p = L;   
	int j = 0;
	while (p && j < i-1) {  // 寻找第i-1个结点
		p = p->next;
		++j;
	} 
	if (!p || j > i-1) 
		return 0;                   // i小于1或者大于表长
	s = (LinkList)malloc(sizeof(LNnode));  // 生成新结点
	s->data = e;  s->next = p->next;      // 插入L中
	p->next = s;
	return 1;	
}

void ListTraverse(LinkList L,void(*vi)(ElemType))
{ 	// 初始条件:单链表L已存在。
	//操作结果:依次对L的每个数据元素调用函数vi()
	LinkList p=L->next;
	while(p)
	{
		vi(p->data);
		p=p->next;
	}
	printf("\n");	
}

void reverse (LinkList &L)
{  
	//逆置L指针所指向的单链表
	/********** Begin **********/ 
	LinkList p,q;
	p=L->next;
	L->next=NULL;
	while(p != NULL){
		q=p;
		p=p->next;
		q->next=L->next;
		L->next=q;
	}
	/********** End **********/
}

第6关:两个有序单链表的合并操作

任务描述

本关任务:分别输入两个有序的整数序列(分别包含M和N个数据),建立两个有序的单链表,将这两个有序单链表合并成为一个大的有序单链表。要求合并后的单链表仍使用原来两个链表的存储空间,不另外占用其他的存储空间。

测试说明

平台会对你编写的代码进行测试:

测试输入:
5
10 15 20 25 30
6
12 22 32 42 52 62

输入说明
第一行输入有序表A的长度M;
第二行依次输入有序表A的M个有序的整数;
第三行输入有序表B的长度N;
第四行依次输入有序表B的N个有序的整数。

预期输出:
合并两个有序单链表:
10 12 15 20 22 25 30 32 42 52 62

输出说明
第一行输出提示信息;
第二行输出合并后的有序单链表所包含的M+N个有序的整数。

代码如下

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

/* 定义ElemType为int类型 */
typedef int ElemType;
void input(ElemType &s);
void output(ElemType s);
int equals(ElemType a,ElemType b);

/* 单链表类型定义 */
typedef struct LNnode
{	
	ElemType data;
	struct LNnode *next;
}LNnode,*LinkList;
void InitList(LinkList &L);
int ListInsert(LinkList &L,int i,int e) ;
void ListTraverse(LinkList L,void(*vi)(ElemType));
void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc);

int main()               //main() function 
{	
	LinkList A,B,C;
	ElemType e;
	InitList(A);
	InitList(B);
	int n,i;
	// cout<<"Please input the list number ";
	cin>>n;
	for(i=1;i<=n;i++)
	{ 
		cin>>e;
		ListInsert(A, i, e);
	}
	cin>>n;
	for(i=1;i<=n;i++)
	{ 
		cin>>e;
		ListInsert(B, i, e);
	}
	cout<<"合并两个有序单链表:"<<endl;
	MergeList(A,B,C);	
	ListTraverse(C,output) ;	
}

/*****ElemType类型元素的基本操作*****/
void input(ElemType &s)
{
	cin>>s;
}
void output(ElemType s)
{
	cout<<s<<" ";
}
int equals(ElemType a,ElemType b)
{
	if(a==b)
		return  1;
	else
		return  0;
}

/*****单链表的基本操作*****/
void InitList(LinkList &L)
{ 	// 操作结果:构造一个空的单链表L
	L=(LinkList)malloc(sizeof(LNnode)); // 产生头结点,并使L指向此头结点
	if(!L) // 存储分配失败
		return ;
	L->next=NULL; // 指针域为空	
}

int ListInsert(LinkList &L,int i,ElemType e) 
{	// 在带头结点的单链线性表L的第i个元素之前插入元素e  
	LinkList p,s;
	p = L;   
	int j = 0;
	while (p && j < i-1) {  // 寻找第i-1个结点
		p = p->next;
		++j;
	} 
	if (!p || j > i-1) 
		return 0;                   // i小于1或者大于表长
	s = (LinkList)malloc(sizeof(LNnode));  // 生成新结点
	s->data = e;  s->next = p->next;      // 插入L中
	p->next = s;
	return 1;	
}

void ListTraverse(LinkList L,void(*vi)(ElemType))
{ 	// 初始条件:单链表L已存在。
	//操作结果:依次对L的每个数据元素调用函数vi()
	LinkList p=L->next;
	while(p)
	{
		vi(p->data);
		p=p->next;
	}
	printf("\n");	
}

void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc) 
{
	// 已知单链线性表La和Lb的元素按值非递减排列。
	// 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列。
	/********** Begin **********/ 
	LinkList pa,pb,pc;
	pa=La->next;
	pb=Lb->next;
	Lc=La;
	pc=Lc;
	while(pa && pb){
		if(pa->data <= pb->data){
			pc->next=pa;pc=pa;pa=pa->next;
		}else{
			pc->next=pb;pc=pb;pb=pb->next;
		}
	}
    pc->next=pa?pa:pb;
	free(Lb);
	/********** End **********/
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐