- 题目内容
已知由一个线性链表表示的线性表中含有三类字符的数据元素(如字母字符、数字字符、其他字符),试编写算法将该线性链表分割为三个循环链表,其中每个循环链表表示的线性表中均只含一类字符。
- 算法分析
首先建立三个只有头结点的单循环链表,分别是其他字符单链表A、数字单链表B、字母单链表C。然后从已知单链表中读取结点,如果结点的值域为其他字符,则将其插入到字符单循环链表中;如果结点的值域是字母,则插入到字母单循环链表;如果结点的值域为数字,则插入到数字单循环链表。最后一定要记得设置每个链表的最后一个结点的指针域,让其指向头结点。
- 概要设计
本算法设计了函数:
_buynode()函数
Initial()函数
push_back()函数
Print()函数
Divide()函数
main()主函数
main()主函数
算法流程图
源代码
/*******
@author:sy
@date:2021-10-6
@version:1.0
@Description:将一个线性表分割为三个分别只含一类字符的循环链表
********/
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
#define Elemtype char
/*定义结构体*/
typedef struct Node
{
Elemtype data;
struct Node *next;
}Lnode;
Node* _buynode(Elemtype data);
void Initial(Lnode **head);
void push_back(Lnode *head,Elemtype data);
void Print(Lnode *head);
void Divide(Lnode *A,Lnode *B,Lnode *C);
int main()
{
Lnode *A,*B,*C;
Initial(&A);
Initial(&B);
Initial(&C);
printf("请构造字符类型的单循环链表,输入三种不同的字符(*结束)\n");
int data;
while(1)
{
scanf("%c",&data);
if(data=='*')
break;
push_back(A,data);
}
printf("构造完成的链表>>>");
Print(A);
Divide(A,B,C);
printf("分割过后的单循环链表\n");
Print(A);
Print(B);
Print(C);
return(1);
}
Lnode* _buynode(Elemtype data)
{ //申请一个新的节点,节点的数据域赋值为x
//最后返回这个节点的指针
Lnode *s=(Node*)malloc(sizeof(Lnode));
assert(s!=NULL); //assert()函数功能:如果条件错误则终止程序进行
s->data=data;
s->next=NULL;
return(s);
}
void Initial(Lnode **head)
{ //初始化单循环链表
(*head)=(Lnode*)malloc(sizeof(Lnode));
assert((*head)!=NULL);
(*head)->next=*head;
(*head)->data=0;//表长为0
}
void push_back(Lnode *head,Elemtype data)
{
//在单循环链表的尾部插入一个新的节点
//把数据域赋值为data
Lnode *s=_buynode(data);
Lnode *p=head;
while(p->next!=head)
p=p->next;//p指向链表的尾部节点
s->next=p->next;
p->next=s;
head->data++;//表长加一
}
void Print(Lnode *head)
{ //算法的前提是单循环链表至少有一个节点
// 依次显示单循环链表中的数据元素
if(head->data==0)
return;//表长合法性判断
Lnode *p=head;
while(p->next!=head)
{
printf("%c-->",p->next->data);
p=p->next;
}
printf("head.\n");
}
void Divide(Lnode *A,Lnode *B,Lnode *C)
{ //算法的前提是三个链表已经初始化,并且A链表至少有三个不同的字符数据
// 把链表A分割成三个链表a,b,c
//A中存储其他字符,B,C中分别存储数字字符和字母字符
Lnode *pa=A;
while(pa->next!=A)
{
if(pa->next->data<='9' && pa->next->data>='0')
{
Lnode *q=pa->next;
pa->next=q->next;//将数字字符的节点从A链表中摘下来
Lnode *pb=B->next;
while(pb->next!=B)
pb=pb->next;//pb指向B链表中的尾节点
q->next=pb->next;
pb->next=q;//尾部插入
B->data++;//表长加一
}
else if(pa->next->data<='Z'&&pa->next->data>='A' || pa->next->data<='z'&&pa->next->data>='a')
{
Lnode *q=pa->next;
pa->next=q->next;//将字符字符从A链表中摘下来
Lnode *pc=C->next;
while(pc->next!=C)
pc=pc->next;//pc指向C链表中的尾部节点
q->next=pc->next;
pc->next=q;
C->data++;//表长加一
}
else
pa=pa->next;
}
}
assert()函数,它的功能是如果内部条件错误,则终止程序进行,此函数的优点就是方便我们进行程序调试,同时对于绝对不能出错的地方使用可以有效的预防出现更多的错误,但它的缺点是频繁的调用会增加额外yun'xi的开销,影响程序性能。
运行结果