单链表运算

本文详细介绍了单链表的基本操作,包括使用头插法和尾插法建立链表的方法,并对比了两种方法的特点。此外,还讲解了如何进行单链表的查找、插入和删除操作。

一 建立单链表

延续前面的定义,数据取字符型,以/n作为输入结束条件,动态建立单链表通常分为头插法和尾插法,下面将一一描述。

(1)头插法

算法思路:将新节点插入到当前节点的头部,直到读入结束标志符为止


这种方式生成的链表节点次序与输入的次序相反


头插法具体算法代码

<pre name="code" class="cpp">LinkList CreatListH(void)
{
	char ch;
	LinkList head;//头指针
	ListNode *s;	//工作指针
	head = NULL;	//链表开始为空
	ch = getchar();	//读取第一个字符
	while(ch!='\n')
	{
		s = (ListNode *)malloc(sizeof(ListNode));//生成新的节点
		if(!s)
		{
			printf("申请内存失败");
			return NULL;
		}
				s->data = ch; //将读入的数据放入新节点数据域
				s->next = head;head = s;
				ch = getchar(); //读入下一个字符
		}
				return head;
}





(2)尾插法

算法思路:将新节点当前节点的尾部,直到读入结束标识符

这种方式生成的链表顺序与输入顺序一致,但是需要增加一个尾指针r,使其始终指向当前节点的尾节点

尾插法具体算法代码

LinkList CreatListT(void)
{
	char ch;
	LinkList head;//头指针
	ListNode *s,*r;//工作指针
	head = NULL;	//链表开始为空
	r = NULL;
	ch = getchar();	//读入第一个字符
	while(ch!='\n')
	{
		s = (ListNode *)malloc(sizeof(ListNode));//生成新节点
		if(!s)
		{
			printf("申请内存失败");
			return NULL;
		}
		s->data = ch;//将读入的数据放入新节点的数据域
		if(head==NULL)
			head = s;	//将新节点插入空表
		else
			r->next = s;//将新节点插入到*r之后
		ch = getchar();//读入下一个字符
	}
	if(r!=NULL)
		r->next = NULL;//对于非空表,将表尾指向指针域,置空head=s
	return head;
}

注:以上俩个方法时间复杂度均为O(n)

二 单链表查找

(1)按序号查找

计数器j置为0后,扫描指针p指针从链表的头结点开始顺着链扫描。当p扫描下一个结点时,计数器j相应地加1。当j=i时,指针p所指的结点就是要找的第i个结点。而当p指针指为null且j≠i时,则表示找不到第i个结点。
注意:头结点可看做是第0个结点。


算法思想:

ListNode * GetNode(LinkList head,int i)
{
	//在带头结点的单链表head中查找第i个结点,若找到(0≤i≤n),
      //则返回该结点的存储位置,否则返回NULL
	int j;
	ListNode *p;
	p = head,j = 0;//从头开始扫描
	while(p->next&&j<i){
		p = p->next;
		j++;
	}
	if(i==j)
		return p;//找到了第i个结点
	else 
		return NULL;
}
算法分析:

最多距离为i,这与气位置有关,在等概率假设情况下,平均时间复杂度为



(2)按值查找

算法思想:

ListNode * LocateNode(ListNode head,DataType key)
{
	ListNode *p = head->next;//设置开始比较的节点
	while(p&&p->data!=key)//直到p为NULL或者p->data为key
		p = p->next;//扫描下一个节点
	return  p;
}

算法分析:

 该算法的执行时间亦与输入实例中key的取值相关,其平均时间复杂度分析类似于按序号查找,为O(n)。


三 插入运算

插入运算思想 :将值为x的新结点插入到表的第i个结点的位置上,即插入到ai-1与ai之间。

具体步骤:
 (1)找到ai-1存储位置p
 (2)生成一个数据域为x的新结点*s
 (3)令结点*p的指针域指向新结点
 (4)新结点的指针域指向结点ai。


具体算法实现 :

void InsertList(LinkList head,DataType x,int i)
{
	//将值为x的新节点插入到带头结点单链表head
	//的第i个节点位置
	ListNode *p;
	p = GetNode(head,i-1);//寻找第i-1个节点
	if(p==NULL)
		Error("position error");
	s = (ListNode *)malloc(sizeof(ListNode));
	s->data = x;
	s->next = p->next;
	p->next = s;
}

算法分析:

主要集中在GetNode上,因此时间复杂度仍旧为O(n)


四  删除运算

具体步骤:
 (1)找到ai-1的存储位置p(因为在单链表中结点ai的存储地址是在其直接前趋结点ai-1的指针域next中)
 (2)令p->next指向ai的直接后继结点(即把ai从链上摘下)
 (3)释放结点ai的空间,将其归还给"存储池"。
记得释放内存就好


具体算法实现:

void DeleteList(LinkList head ,int i)
{
	//删除带头结点的第i个节点
	ListNode *p,*r;
	p = GetNode(head,i-1);//找到第i-1个节点
	if(p==NULL||p->next==NULL)
		Error("position error");
	r  = p->next;//r指向被删除结点的ai
	p->next = r->next;//将ai从链上取下
	free(r);//释放节点
}

算法分析:

时间复杂度也是O(n)




                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值