循环单链表的应用

  • 题目内容

已知由一个线性链表表示的线性表中含有三类字符的数据元素(如字母字符、数字字符、其他字符),试编写算法将该线性链表分割为三个循环链表,其中每个循环链表表示的线性表中均只含一类字符。 

  • 算法分析

 首先建立三个只有头结点的单循环链表,分别是其他字符单链表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的开销,影响程序性能。

 运行结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值