【c】链表的操作!!!

//c语言里面单链表的一些基本操作
void PushFront(pNode *head,Datatype d)            //push data from front
{
	Node *p = *head;
	Node *New = malloc(sizeof(Node));
	if (New == NULL)
	{
		perror("::");
		exit(EXIT_FAILURE);
	}
	New->data = d;
	New->next = NULL;
	if (p == NULL)
	{
		*head = New;
	}
	else
	{
		New->next = p;
		*head = New;
	}
}


void PushBack(pNode *phead,Datatype d)              //push data from back
{
	Node *p = *phead;
	Node *New = malloc(sizeof(Node));
	if (New == NULL)
	{
		perror("::");
		exit(EXIT_FAILURE);
	}
	New->data = d;
	New->next = NULL;
	if (p == NULL)
	{
		*phead = New;
	}
	else
	{
		while (p->next)
		{
			p = p->next;
		}
		p->next = New;
	}
}  


void Display(Node *head)                               //display link list
{
	if (head == NULL)
	{
		return ;
	}
	while (head)
	{
		printf("%d-->",head->data);
		head = head->next;
	}
	printf("\n");
}


void DelFront(pNode *phead)                        //delete from front
{
	Node *p = *phead;
	Node *del = *phead;
	if (del == NULL)
	{
		return ;
	}
	*phead = p->next;
	free(del);
}


void DelBack(pNode *phead)                       //delete from back
{
	Node *p = *phead;
	Node *del = *phead;
	if (p == NULL)
	{
		return ;
	}
	if (p->next == NULL)
	{
		*phead = NULL;
		free(del);
		exit(EXIT_SUCCESS);
	}
	while (del->next)
	{
		p = del;
		del = del->next;
	}
	p->next = NULL;
	free(del);
}


void PushkBackPlace(pNode *phead,Datatype k,Datatype d)                //push data from back of this data is k
{
	Node *p = *phead;
	Node *New = malloc(sizeof(Node));
	if (New == NULL)
	{
		perror("::");
		exit(EXIT_FAILURE);
	}
	New->data = d;
	New->next = NULL;
	if (p == NULL)
	{
		return ;
	}
	while (p->next)
	{
		if (p->data == k)
		{
			New->next = p->next;
			p->next = New;
		}
		p = p->next;
	}
}


void PushkFrontPlace(pNode *phead,Datatype k,Datatype d)               //add a node from the front of k
{
	Node *pk = NULL;
	Node *p = *phead;
	Node *New = malloc(sizeof(Node));
	if (New == NULL)
	{
		perror("::");
		exit(EXIT_FAILURE);
	}
	New->data = d;
	New->next = NULL;
	while (p)
	{
		pk = p;
		p = p->next;
		if (p->data == k)
		{
			New->next = pk->next;
			pk->next = New;
			break;
		}
	}
}




 void Delkplace(pNode *phead,Datatype k )                       //delete a node from the front of k 
 {
	Node *p = *phead;
	if (p == NULL)
	{
		return ;
	}
	while (p->next)
	{
		if (p->data == k)
		{
			Node *del = p->next;
			p->data = del->data;
			p->next = del->next;
			free(del);
		}
		p = p->next;
	}
 }






 void  Pushkfront(pNode *phead,Datatype k,Datatype d)        //add a node from k
 {
	Datatype tmp = 0;
	Node *p = *phead;
	Node *New = malloc(sizeof(Node));
	if (New == NULL)
	{
		perror("::");
		exit(EXIT_FAILURE);
	}
	New->next = NULL;
	New->data = d;


	while (p)
	{
		if (p->data == k)
		{
			New->next = p->next;
			p->next = New;
			tmp = New->data;
			New->data = p->data;
			p->data = tmp;
			break;
		}
		p = p->next;
	}
 }


 void PutListToCircle(pNode *phead)                 //make the link list up a circle
 {
	 Node *p = *phead;
	 if (p == NULL)
	 {
		 return ;
	 }
	 while (p->next)
	 {
		 p = p->next;
	 }
	 p->next = *phead;
 }


 int JudgeListforCircle(pNode *phead)                    //judge a link list is a circle or not?
 {
	 Node *fast = *phead;
	 Node *slow = *phead;
	 
	 while (fast)
	 {
		 if (fast->next == NULL)
		 {
			 return -1;
		 }
		 fast = fast->next->next;
		 slow = slow->next;
		 if (fast == slow&&fast)
		 {
			 return 1;
		 }
	 }
	 return -1;
 }




 Node* _JudgeListforCircle(pNode *phead)
 {
	 Node *fast = *phead;
	 Node *slow = *phead;


	 while (fast)
	 {
		 if (fast->next == NULL)
		 {
			 return NULL;
		 }
		 fast = fast->next->next;
		 slow = slow->next;
		 if (fast == slow&&fast)
		 {
			 return fast;
		 }
	 }
	 return NULL;
 }




 int DecldeListLong(pNode *phead)                    //how long the link list?
 {
	 int count = 0;
	 Node *p = NULL;
	 Node *aim = NULL;
	 aim = _JudgeListforCircle(phead);
	 p = aim->next;
	 while (p)
	 {
		 count++;
		 if (p == aim)
		 {
			 break;
		 }
		 p = p->next;
	 }
	 return count;
 }
Node * BackLinkList(pNode *phead)      //swap link list 
{
	Node *tmp = NULL;
	Node *cur = NULL;
	Node *p = *phead;
	while (p)
	{
		tmp = p->next;
		p->next = cur;
		cur = p;
		p = tmp;
	}
	return cur;
}


Node * _BackLinkList(pNode head)             //swap link list
{
	Node *Newhead = NULL;
	if (head == NULL || head->next == NULL)
	{
		return head;
	}
	Newhead = _BackLinkList(head->next);
	head->next->next = head;
	head->next = NULL;
	return Newhead;
}
1、找出单链表的倒数第K个元素(仅允许遍历一遍链表)


     使用指针追赶的方法。定义两个指针fast和slow,fast先走K步,然后fast和slow同时继续走。当fast到链表尾部时,slow指向倒数第K个。注意要考虑链表长度应该大于K。
2、找出单链表的中间元素(仅允许遍历一遍链表)


     使用指针追赶的方法。fast每次走一步,slow每次走两步。当fast到链表尾部时,slow指向链表的中间元素。


3、判断单链表是否有环?


     方法一:使用指针追赶的方法。slow指针每次走一步,fast指针每次走两步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。


     方法二:使用p、q两个指针,p总是向前走,但q每次都从头开始走。
4、如何知道环的长度?


     记录下碰撞点(或者找在环中任意一结点都可以),让slow从碰撞点开始,绕着环走一圈,再次到碰撞点的位置时,所走过的结点数就是环的长度s。
5、如何找到环的入口?
    
     分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
6、判断两个链表(无环)是否相交?


     方法一:采用暴力的方法,遍历两个链表,在遍历的过程中进行比较,看节点是否相同。


     方法二:两链表一旦相交,相交节点一定有相同的内存地址,因此利用内存地址建立哈希表,如此通过判断两个链表中是否存在内存地址相同的节点判断两个链表是否相交。具体做法是:遍历第一个链表,并利用地址建立哈希表,遍历第二个链表,看看地址哈希值是否和第一个表中的节点地址值有相同即可判断两个链表是否相交。时间复杂度O((length(A)+ length(B))


     方法三:问题转化法。先遍历第一个链表到其尾部,然后将尾部的原本指向NULL的next指针指向第二个链表。这样两个链表就合成了一个链表,问题转变为判断新的链表是否有环?


     方法四:一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点。所以,如果他们相交的话,那么他们最后的一个节点一定是相同的,因此分别遍历到两个链表的尾部,然后判断他们是否相同。
7、如何知道两个单链表(可能有环)是否相交


思路:根据两个链表是否有环来分别处理,若相交这个环属于两个链表共有


(1)如果两个链表都没有环。


(2)一个有环,一个没环。肯定不相交


(3)两个都有环。
     ①求出A的环入口,判断其是否在B链表上,如果在,则相交。
     ② 在A链表上,使用指针追赶的方法,找到两个指针碰撞点,之后判断碰撞点是否在B链表上。如果在,则相交。
8、寻找两个相交链表的第一个公共节点  


     方法一:最简单的方法就是先顺序访问其中一个链表,在每访问一个节点时,都对另外一个链表进行遍历,直到找到一个相等的节点位置,如果链表长度分别是m,n 则时间复杂度为O(mn)。


     方法二:(两种情况)
            
     ① 相交的点,在环外。如果两个链表有公共节点,那么该公共节点之后的所有节点都是两个链表所共有的,所以长度一定也是相等的,如果两个链表的总长度是相等的,那么我们对两个链表进行遍历,则一定同时到达第一个公共节点。但是链表的长度实际上不一定相同,所以计算出两个链表的长度之差n,然后让长的那个链表先移动n步,短的链表再开始向后遍历,这样他们一定同时到达第一个公共节点,我们只需要在向后移动的时候比较两个链表的节点是否相等就可以获得第一个公共节点。时间复杂度是O(m+n)。


           
     ② 相交的点在环内。当交点在环中时,此时的交点可以是A链表中的环入口点,也可以是B链表中环入口点。这是因为如果把B看出一个完整的链表,而A指向了B链表,则此时交点是A的环入口点。反之交点是链表B的环入口点。     
     思路:根据上述分析,可以直接求出A的环入口点或者B的环入口点就可以了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值