C语言数据结构之链表部分(10)

10.练习

统计单向链表的每个元素出现的次数
#include <stdio.h>
#include <stdlib.h>
#define N 11

typedef struct node
{
      int data;
      int times;
      struct node * next;
}ElemSN;
ElemSN * Createlink(int a[]);
void  Printlink(ElemSN *h);
int main()
{
      ElemSN *head;
      int a[N] = {2,3,5,7,2,3,7,2,5,3,7};
      //创建
      head = Createlink(a);
      //打印
      Printlink(head);
      printf("\n");

      return 0;
}
ElemSN * Createlink(int a[])
{
      ElemSN *h,*t,*p;
      h = NULL;
      for(int i = 0;i < N;i++)
      {
            for(p = h;p && p->data != a[i];p = p->next);
            if(!p)
            {
                  p = (ElemSN *)malloc(sizeof(ElemSN));
                  p->data = a[i];
                  p->times = 1;
                  p->next = NULL;
                  if(!h)
                  {
                        h = t = p;
                  }
                  else
                  {
                        t = t->next = p;
                  }
            }
            else
            {
                  p->times++;
            }
      }
      return h;
}

void  Printlink(ElemSN *h)
{
      ElemSN *p;
      for(p = h;p != NULL;p = p->next)
      {
            printf("%d %d\n",p->data,p->times);
      }
}

判断是否出现交叉
#include <stdio.h>
#include <stdlib.h>
#define N 8
typedef struct node
{
      int data;
      struct node * next;
}ElemSN;
ElemSN * Createlink1(int a[]);//创建
void Printlink(ElemSN *h);//打印
ElemSN * mixnode(ElemSN *h1,ElemSN *h2);//判断是否有交叉点
int main()
{
      ElemSN *head,*head1,*head2,*p,*q;
      int a[N] = {3,6,5,8,4,7,2,1};
      int i =0;
      //创建
      head = Createlink1(a);
      //打印原链表
      Printlink(head);
      printf("\n");
      //将原链表变成交叉链表

      p = head;    //头结点是3,p指向3
      head = head->next;    //将head后移1个,变成head指向6
      for(q = head;i < 3;q = q->next,i++);   //现在 q 在 4 上指着呢
      p->next = q->next;    //把 7 也变成了 3 的后继
      head1 = head;    //链表1是 6,5,8,4,7,2,1
      head2 = p;    //链表2是 3,7,2,1

      //判断是否有交叉点
      head = mixnode(head1,head2);
      printf("第一个交叉点是:%d\n",head->data);


      return 0;
}
ElemSN * Createlink1(int a[])
{
      ElemSN *head,*tail,*p;
      int i;
      head = tail = (ElemSN *)malloc(sizeof(ElemSN));
      head->data = a[0];
          head->next = NULL;
      for(i = 1;i < N;i++)
      {
            p = (ElemSN *)malloc(sizeof(ElemSN));
            p->data = a[i];
            p->next = NULL;
            tail->next = p;
            tail = p;
      }
      return head;
}
void Printlink(ElemSN *h)
{
      ElemSN *p;
      for(p = h;p != NULL;p = p->next)
      {
            printf("%d ",p->data);
      }
}
//判断是否有交叉点
ElemSN * mixnode(ElemSN *h1,ElemSN *h2)
{
      ElemSN **s1,**s2;
      ElemSN *p;
      s1 = (ElemSN **)malloc(100*sizeof(ElemSN *)); //建立栈s1
      s2 = (ElemSN **)malloc(100*sizeof(ElemSN *));//建立栈s2
      //将链表1元素的地址放到栈s1里面
      int n1 = 0;
      for(p = h1;p;s1[n1++] = p,p = p->next);
      s1[n1] = 0;
      //将链表2元素的地址放到栈s2里面
      int n2 = 0;
      for(p = h2;p;s2[n2++] = p,p = p->next);
      s2[n2] = 0;
      //将栈s1和栈s2从顶元素开始向下比较
      while(n1 != -1 && n2 != -1 && s1[n1] == s2[n2])
      {
            n1--;
            n2--;
      }
      if(n1 == -1)
      {
            return s1[n1+1];
      }
      else if(n2 == -1)
      {
            return s2[n2+1];
      }
      else
      {
            return s1[n1+1];
      }

}
    
方法2(最优,时间复杂度O(n),空间复杂度O(1))
#include <stdio.h>
#include <stdlib.h>
#define N 8
typedef struct node
{
      int data;
      struct node * next;
}ElemSN;
ElemSN * Createlink1(int a[]);//创建
void Printlink(ElemSN *h);//打印
ElemSN * mixnode(ElemSN *h1,ElemSN *h2);//判断是否有交叉点
int main()
{
      ElemSN *head,*head1,*head2,*p,*q;
      int a[N] = {3,6,5,8,4,7,2,1};
      int i =0;
      //创建
      head = Createlink1(a);
      //打印原链表
      Printlink(head);
      printf("\n");
      //将原链表变成交叉链表

      p = head;    //头结点是3,p指向3
      head = head->next;    //将head后移1个,变成head指向6
      for(q = head;i < 3;q = q->next,i++);   //现在 q 在 4 上指着呢
      p->next = q->next;    //把 7 也变成了 3 的后继
      head1 = head;    //链表1是 6,5,8,4,7,2,1
      head2 = p;    //链表2是 3,4,7,2,1

      //判断是否有交叉点
      head = mixnode(head1,head2);
      printf("第一个交叉点是:%d\n",head->data);


      return 0;
}
ElemSN * Createlink1(int a[])
{
      ElemSN *head,*tail,*p;
      int i;
      head = tail = (ElemSN *)malloc(sizeof(ElemSN));
      head->data = a[0];
      head->next = NULL;
      for(i = 1;i < N;i++)
      {
            p = (ElemSN *)malloc(sizeof(ElemSN));
            p->data = a[i];
            p->next = NULL;
            tail->next = p;
            tail = p;
      }
      return head;
}
void Printlink(ElemSN *h)
{
      ElemSN *p;
      for(p = h;p != NULL;p = p->next)
      {
            printf("%d ",p->data);
      }
}
//判断是否有交叉点
ElemSN * mixnode(ElemSN *h1,ElemSN *h2)
{
      ElemSN *p,*p1,*p2;
      int n,n1 = 0,n2 = 0;
      for(p = h1;p;n1++,p = p->next); //统计链表1的结点数
      for(p = h2;p;n2++,p = p->next); //统计链表2的节点数
      n = n1 - n2;
      if(n < 0)   //即链表2长于链表1,将h1和h2指针互换,保证h1指向的永远是最长的那根链表
      {
            n = -n;
            p = h2;
            h2 = h1;
            h1 = p;
      }
      for(p1 = h1;n;p1 = p1->next,n--);//先让长链表指针h1跳 n 个结点
      for(p2 = h2;p1 != p2;p1 = p1->next,p2 = p2->next); //同步跳,直到相等时就是第一个交叉链表
      return p1; //返回p1和p2是一样的,因为p1和p2此时指向的是同一个结点
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值