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此时指向的是同一个结点
}