第二章线性表王道练习题统考题

21.(p43)思路:

  • 定义p,q指针,初始时均指向头结点的下一个结点,令p结点向下移动当p节点移动到第k个节点时,q指针开始与p指针一起移动。这样当p指针移动到最后一个是q指针指向倒数第k个节点
 int find_font(DLinklist L)
 {
 	int k=1,count=0;
 	printf("请输入k:\n");
 	scanf("%d",&k);
 	DLinklist p=L->next,q=L->next;
 	while(p!=NULL)
 	{
 		if(count<k)
 		{
 			count++;
		 }
		 else
		 {
		 	q=q->next;
		 }
		 p=p->next;
	 }
	 if(count<k)
	 {
	 	printf("false;\n");
	 	return 0;
	 }
	 else
	 {
	 	printf("%d\n",q->data);
	 	return 1;
	 }
  }

22.(p43)思路

  • 定义两个指针p,q在两个链表上,求出两个单链表的长度m,n。令k=abs(m-n)+1 若 m>n则先移动p 当p移动到第k个节点时q开始移动。这样保证p,q指针所指的节点到尾节点的距离相同然后进行while循环直至p,q指针指向相同的结点。若直到p/q=NULL依然没有指向相同的节点则表明两个单词无相同的后缀
  • 22题的思路与21的思路有相同之处。22题是L1,L2链表从某一节点开始后面的节点位置一致,求这一节点:因为L1,L2链表的长度不同,所以指针在唱的链表上先走,当剩余节点数与短链表中的节点数一致时,短链表上的指针开始与长链表指针一起移动,这样抱枕里长短链表上的指针同时移到共同后缀的起始位置。总结下来就是让两指针同时到达链尾。
DLinklist same(DLinklist L1,DLinklist L2)
  {
  	DLinklist str1=L1,str2=L2,p,q;
  	int m=print(L1);
  	int n=print(L2);
  	for(p=str1;m>n;m--)
  	{
  		p=p->next;
	  }
	  for(q=str2;m<n;n--)
	  {
	  	q=q->next;
	  }
	  while(p->next!=NULL&&p->next!=q->next)
	  {
	  	p=p->next;
	  	q=q->next;
	  }
	  return p->next;
  }
  

23题

  • 我自己代码的时间复杂度为: O ( n 2 ) O( n^{2} ) O(n2)有点大了。我的思路与书上的思路最大的不同之处是我将出现过的数值的绝对值依次放在数组中,在判断节点绝对值是否出现过时,我遍历数组去找节点的绝对值,这种做法令时间复杂度增大。
  • 书上的做法是:因为 ∣ d a t a ∣ < n |data| < n data<n 所以申请一个 ( n + 1 ) (n+1) n+1大小的数组 M M M,令 M M M初始值为0,若出现一个值 d 1 d1 d1,令M[|d1|]=1 (我的做法是:若|d1|是第n个以往都没有出现的值则令M[n]=|d1|)
  • 我的代码:
  int find(int data[],int x)   //判断x是否在数组data中 
 {
 	for(int i=0;data[i]!='\0';i++)
 	{
 		if (data[i]==x)
 			return 1;
	 }
	 return -1;
 }

void deletesame(DLinklist L)
  { 
  	int data1[100],i=0,j=0;
  	DLinklist p=L->next,q=p,end=L;
  	L->next=NULL;
  	while(p!=NULL)
  	{
  		q=p->next;
  		if(find(data1,abs(p->data))==-1)
  		{
  			int x=abs(p->data);
  			data1[i]=x;
  			i++;
  			end->next=p;
  			p->next=NULL;
  			end=p;
  			p=q;
		  }
		  else
		  {
		  	p=p->next;
		  }
	  } 
  }

书上的代码:

 void deletesame(DLinklist L)
  {
  	//法一:
  	int data1[100]={0},i=0,j=0;
	DLinklist p=L->next,q=p,end=L;
  	L->next=NULL;
  	while(p!=NULL)
  	{
  		q=p->next;
  		if(data1[abs(p->data)]==0)
  		{
  			data1[abs(p->data)]=1;
  			end->next=p;
  			p->next=NULL;
  			end=p;
  			p=q;
		  }
		  else
		  {
		  	p=p->next;
		  }
	  } 
}

25题

  • 思路:找到链表中间的结点将链表分成2个链表L1,L2,将后面的链表转置,将p,q结点分别指向L1,L2头结点的后一个节点。将q结点插到p节点的后边。遍历L1,L2。
void range(DLinklist L)
  {
  	int i=0,m=0;
	DLinklist p=L->next;
	while(p!=NULL)
	{
	    i++;
		p=p->next;
	 }
	 p=L->next;
	 if(i%2==0)
	 {
	 	m=i/2;
	 }
	 else
	 {
	 	m=(i+1)/2;
	 }      //找链表的中间节点
	 int count=1;
	 for(count=1;count<m;count++)
	 {
	 	p=p->next;
	 }
	DLinklist r=p->next,p1; 
	p->next=NULL;
	p1=p=L->next;
	DLinklist q=r,L1;
	L1=(DLinklist)malloc(sizeof(DNode));
 	L1->next=r;
	diverse(L1);
	/*
	printf("L1:\n");
	print(L1);
	printf("\n");
	printf("*****************\n");
	printf("L:\n");
	print(L);
	printf("\n");
	printf("======================\n");
	*/
	DLinklist q1=L1->next,q2=q1;
	while(q1!=NULL)
	{
		q2=q1->next;
		p1=p->next;
		q1->next=p->next;
		p->next=q1;
		q1=q2;
		p=p1;
	}
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值