实验2-单链表的建立及操作-数据结构(C语言)

实验2 单链表的建立及操作

  • 实验要求

1.建立一个带头结点的单链表,结点的值域为整型数据。要求将用户输入的数据按尾插入法来建立相应单链表。

2.设计一个函数在链表中查找元素x的位置,如果x不在链表中则返回-1。

3.设计一个函数将元素x插入第i个元素的后面。如果i大于链表的长度,则将x插入链表的末尾,如果i小于或等于0,则将x直接插入表头之后。

  • 实验过程及结果
    1.基本思路
    定义一个结点的值域为int型数据,创建一个头结点,先初始化,将它的next指针置为NULL,正位序插入n个元素的值,建立带表头结点的单链表L。
    代码显示:
//单链表的建立-尾插法
 int CreateList_R(LinkList &L,int n)//正位序插入n个元素的值,建立带表头结点的单链表L 
 {
 	L=new Lnode;L->next=NULL;//建立头结点 
 	LinkList p,r;
 	r=L;
 	for(int i=0;i<n;++i)
 	{
 	  p=new Lnode;//生成新结点, 
	  scanf("%d",&(p->data));//输入元素的值 
	  p->next=NULL;
	  r->next=p;//插入结点到表尾 
	  r=p;//指向新的尾结点	
	 }
	 return 1;
 }

2.基本思路
先初始化链表使从链表的第一个数据元素开始顺序查找,查找失败的条件为查找的元素值与链表的值不等,这时将返回-1。
代码显示:

//按值查找-根据指定数据的值查找它的位置序号
int LocateElem_L(LinkList L,ElemType e)
{
	//找到,则返回L中与e值相等的数据元素的位置序号,查找失败,则返回-1 
	LinkList p;
	p=L->next;int j=1;//初始化 
	while(p&&p->data!=e)
	{
		p=p->next;
		j++;
	}
	if(p)return j;
	else
	return F;
}

3*.基本思路*:
要查找的位置元素i有三种情况:第一种是i的范围是1~n(n为单链表的长度)按要求插入即可;第二种是i<=0,则将它插入到表头之后(此时链表没有遍历查找,p指向的是头结点);第三种情况是i>n+1,p指向NULL,所以在表尾插入较简单。
代码显示:

//插入-在L中第i个位置之后插入数据元素e
Status ListInsert(LinkList &L,int i,ElemType e)
{
	LinkList p,s;
	p=L;
	int j=0;
	while(p&&j<(i-1))//寻找第i个结点,p指向第i个结点 
	{
		p=p->next;
		++j;
	}
	if(!p)//当i>表长时,将元素插入表尾
	{
		s=new Lnode;
        s=p->next;
        s->data=e;
        s=NULL;
    }
    else if(j>i-1)//当i<1时将元素插入表头之后 
    {
    	s=new Lnode;
		s->data=e;
        s->next=L->next;
        L->next=s;
	}
	else
	{
		s=new Lnode;
		s->data=e;
		s->next=p->next;p->next=s;//将结点s插入L中 
	}
	return OK;//插入成功,返回1 
}
  

完整代码如下


#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define F -1
#define ERROR 0
typedef int ElemType;
typedef int Status;
typedef struct Lnode//单链表的定义 
{
	ElemType data;//数据域 
	struct Lnode *next;	//指针域 
}Lnode,*LinkList;
LinkList L; 
//建立一个空链表 
Status InitList(LinkList &L)
{
	L=new Lnode;//L=(LinkList)mallo(sizeof(Lnode));
	L->next=NULL;
	return OK; 
}
//判断链表是否为空 
int IsEmpty(LinkList L)
{
	if(L->next)//如果L->next==NULL,则链表为空 
	return 0;
	else
	return 1;
}
//链表的销毁 
Status DestoryList(LinkList &L)
{
	LinkList p;
	while(L)//当链表不为NULL时,则一直释放结点 
	{
		p=L;
		L=L->next;
		delete p;
	}
	return OK;
}
//链表的清空 
Status ClearList(LinkList &L)
{ 
	LinkList p,q;
	p=L->next;//使p指向首元结点 
	while(p)//当p指向的结点为NULL时,结束循环 
	{
		q=p->next;
		delete p;
		p=q;
	}
	L->next=NULL; 
	return OK;
}
//求单链表的长度 
int ListLength(LinkList L)
{
	LinkList p;
	p=L->next;//使p指向首元结点 
	int i=0;
	while(p)//当p为NULL时,循环结束 
	{
		i++;//记录结点个数 
		p=p->next;//结点后移 
	}
	return i;//返回的值是链表中的结点个数(不包括头结点) 
}
//取第i个元素的值 
Status Getelem(LinkList L,int i,ElemType &e)//获取链表中某个数据元素的内容,通过e返回 
{
	LinkList p;
	p=L->next;int j=1;//初始化 
	while(p&&j<i)//向后扫描,直到p指向第i个元素的位置或者p为NULL 
	{
		p=p->next;
		++j;
	}
	if(!p||j>i)//第i个元素不存在 
	return ERROR;
	e=p->data;//取第i个元素的值 
	return OK;
}

//按值查找-根据指定数据的值查找它的位置序号
int LocateElem_L(LinkList L,ElemType e)
{
	//找到,则返回L中与e值相等的数据元素的位置序号,查找失败,则返回-1 
	LinkList p;
	p=L->next;int j=1;//初始化 
	while(p&&p->data!=e)
	{
		p=p->next;
		j++;
	}
	if(p)return j;
	else
	return F;
}
//插入-在L中第i个位置之后插入数据元素e
Status ListInsert(LinkList &L,int i,ElemType e)
{
	LinkList p,s;//插入-在L中第i个位置之后插入数据元素e
	p=L;
	int j=0;
	while(p&&j<(i-1))//寻找第i个结点,p指向第i个结点 
	{
		p=p->next;
		++j;
	}
	if(!p)//当i>表长时,将元素插入表尾
	{
		s=new Lnode;
        s=p->next;
        s->data=e;
        s=NULL;
    }
    else if(j>i-1)//当i<1时将元素插入表头之后 
    {
    	s=new Lnode;
		s->data=e;
        s->next=L->next;
        L->next=s;
	}
	else
	{
		s=new Lnode;
		s->data=e;
		s->next=p->next;p->next=s;//将结点s插入L中 
	}
	return OK;//插入成功,返回1 
}
 
//单链表的删除
Status ListDelete(LinkList &L,int i,ElemType &e)
{
	//删除链表中第i个位置的数据元素
	//先找到第i-1个位置的数据元素
	LinkList p,q;
	p=L;int j=0;
	while((p->next)&&j<i-1)//查找第i-1个位置的数据元素 
	{
		p=p->next;
		++j;
	}
	if(!(p->next)||j>i-1)return ERROR;//删除位置不合理 
	q=p->next;//临时保存被删结点的地址以备释放 
	p->next=q->next;//改变被删结点前驱结点的指针域 
	e=q->data;//保存删除结点的数据域 
	delete q;//释放删除结点的空间 
	return OK;
}

//单链表的建立-尾插法
 int CreateList_R(LinkList &L,int n)//正位序插入n个元素的值,建立带表头结点的单链表L 
 {
 	L=new Lnode;L->next=NULL;//建立头结点 
 	LinkList p,r;
 	r=L;
 	for(int i=0;i<n;++i)
 	{
 	  p=new Lnode;//生成新结点, 
	  scanf("%d",&(p->data));//输入元素的值 
	  p->next=NULL;
	  r->next=p;//插入结点到表尾 
	  r=p;//指向新的尾结点	
	 }
	 return 1;
 }

 //主函数测试
 int main()
{
	ElemType e;int n;
	//测试InitList函数
	if(InitList(L))printf("InitList success!\n"); 
	else
	printf("InitList error\n");
	
	//测试IsEmpty函数	
	if(IsEmpty)printf("LinkList is empty\n");
	else
	printf("LinkList is not empty\n");
	
	//测试CreateList_R函数
	printf("请输入建立单链表的数据元素个数:\n");
	scanf("%d",&n);
	if(CreateList_R(L,n))printf("CreateList success\n");
	
	//测试ListLength函数
	printf("LinkList length is %d\n",ListLength(L));
	
	//测试Getelem函数
	if(Getelem(L,1,e))printf("The first element is %d\n",e);
	else
	printf("The first element is not exist\n");
	
	//测试LocateElem_L函数
	int a2; 
	printf("请输入你要查找的元素,若查找成功,会返回该元素的位置序号\n");
	scanf("%d",&a2); 
	int f=LocateElem_L(L,a2);
	if(f)printf("%d is located at %d\n",a2,f);
	else 
	printf("%d is not located at the LinkList\n",a2);
	
	//测试ListInsert函数
	printf("请输入要插入元素的位置序号及元素的值:\n");
	int c,a3;
	scanf("%d %d",&c,&a3);
	if(ListInsert(L,c,a3))printf("ListInsert success\n");
	
	//测试ListDelete函数
	printf("请输入你要删除元素的位置序号:\n");
	int d;
	scanf("%d",&d);
	if(ListDelete(L,d,e))printf("删除的元素是:%d\n",e);
	else
	printf("Delete error\n");
	
	//测试ClearList函数
	if(ClearList(L))
	printf("ClearList success\n");
	else 
	printf("ClearList error\n");
	
	//测试DestoryList函数
	if(DestoryList(L))printf("DestoryList success\n");
	else
	printf("DestoryList error\n");
	return 0;


测试结果

在这里插入图片描述

  • 实验总结

链式存储结构
结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。
线性表的链式表示又称为非顺序映像或链式映像。

单链表的查找、插入、删除算法时间效率分析

因线性链表只能顺序存取,即在查找时要从头指针找起,查找的时间为O(n);
因线性链表不需要移动元素,只要修改指针,一般情况下时间复杂度为O(1),
但是,如果要在单链表中进行前插或删除操作,由于要从头查找前驱结点,所耗时间复杂度为O(n)。

嘿嘿嘿
洛阳亲友如相问,就说我在敲代码

  • 12
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值