数据结构(C语言) 线性表 链式存储 单链表

/*本程序中所有涉及到位置的地方,下标皆从1开始*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>

#define LIMIT 100
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define INFEASIBLE -2

typedef struct Single
{
    int data;
    struct Single *next;
}*SList,SLinkList;

int SList_Init(SList *head)
{   
    SList node;
    int i;
    *head=(SList)malloc(sizeof(SLinkList));//申请头结点空间并判断是否成功
    if(!(*head))
        exit(INFEASIBLE);
    (*head)->next=NULL;
    printf("请输入表长:");
    scanf("%d",&(*head)->data);
    if((*head)->data<0)//判断输入是否合法
        return ERROR;
    srand(time(0));
    for(i=1;i<=(*head)->data;i++)
    {
        node=(SList)malloc(sizeof(SLinkList));//申请节点空间
        if(!node)
            exit(INFEASIBLE);
        node->data=rand()%LIMIT;
        node->next=(*head)->next;
        (*head)->next=node;//依次插入连接
    }
    return OK;
}//初始化链表

int SList_Show(SList head)
{
    SList p=head->next;
    if(!p)//判断是否为空表
        return ERROR;
    while(p)//依次遍历输出
    {
        printf("%0d ",p->data);
        p=p->next;
    }
    printf("\n");
    return OK;
}//输出表

int SList_Insert(SList head,int Data,int Pos)
{
    SList p=head,q;
    int i=0;
    while(p&&i<Pos-1)//插入位置合法性和终止循环条件:p为NULL
    {
        p=p->next;//指针移位
        i++;
    }
    if(!p||i>Pos-1)//非法条件
        return ERROR;
    q=(SList)malloc(sizeof(SLinkList));//申请节点空间并判断是否成功
    if(!q)
        exit(INFEASIBLE);
    q->data=Data;
    q->next=p->next;
    p->next=q;//插入节点
    head->data++;
    return OK;
}//按位置插入

int SList_Delete_Pos(SList head,int *Data,int Pos)
{
    SList p=head,q;
    int i=0;
    while(p->next&&i<Pos-1)//删除位置合法性和终止循环条件:p->next为NULL
    {
        p=p->next;//指针移位
        i++;
    }
    if(!(p->next)||i>Pos-1)//非法条件
        return ERROR;
    q=p->next;
    p->next=q->next;
    *Data=q->data;//返回目标元素
    free(q);//删除节点
    head->data--;
    return OK;
}//按位置删除

int SList_Delete_Elem(SList head,int Data)
{
    SList p=head,q;
    int flag=0;
    while(p->next)//p->next为NULL终止循环
    {
        if(p->next->data==Data)//删除条件
        {
            flag=1;//标记置1
            q=p->next;
            p->next=q->next;
            free(q);//删除节点
            head->data--;
            continue;
        }
        p=p->next;//指针移位
    }
    if(flag==1)
        return OK;
    else
        return ERROR;
}//按元素删除

int SList_Replace_Pos(SList head,int *Data,int Pos)
{
    SList p=head->next;
    int i=1,data=*Data;
    while(p&&i<Pos)//替换位置合法性和终止循环条件:p为NULL
    {
        p=p->next;//指针移位
        i++;
    }
    if(!p||i>Pos)//非法条件
        return ERROR;
    *Data=p->data;//返回目标元素
    p->data=data;//替换
    return OK;
}//按位置替换

int SList_Replace_Elem(SList head,int Data,int data)
{
    SList p=head->next;
    int flag=0;
    while(p)//p为NULL终止循环
    {
        if(p->data==data)//替换条件
        {
            flag=1;//标记置1
            p->data=Data;//替换
        }
        p=p->next;//指针移位
    }
    if(flag==1)
        return OK;
    else
        return ERROR;
}//按元素替换,data为表中的元素

int SList_Find_Pos(SList head,int *Data,int Pos)
{
    SList p=head->next;
    int i=1;
    while(p&&i<Pos)//查找位置合法性和终止循环条件:p为NULL
    {
        p=p->next;//指针移位
        i++;
    }
    if(!p||i>Pos)//非法条件
        return ERROR;
    *Data=p->data;
    return OK;
}//按位置查找

int SList_Find_Elem(SList head,int Data,int Position[],int *N)
{
    SList p=head->next;
    int j=1,flag=0;
    *N=0;
    while(p)//p为NULL终止循环条件
    {
        if(p->data==Data)//查找条件
        {
            flag=1;//标记置1
            Position[*N]=j;//存储位置
            (*N)++;
        }
        j++;
        p=p->next;//指针移位
    }
    if(flag==1)
        return OK;
    else
        return ERROR;
}//按元素查找

void SList_Show_Length(SList head,int *Length)
{
    *Length=head->data;//返回表长
}//查看表长

void SList_Destroy(SList head)
{
    SList p=head;
    while(head)
    {
        head=head->next;//指针移位
        free(p);//删除节点
        p=head;
    }
    head=NULL;//释放头结点
}//销毁表

void SList_Clear(SList head)
{
    SList p=head->next;
    head->data=0;
    head->next=NULL;//断开头结点
    SList_Destroy(p);//销毁头结点后面的节点
}//清空表

int SList_Josephus(SList head,int k,int *Data)
{
    int flag=1,Pos=1,State;
    if(k<1||!(head->next))//判断条件是否合法:表长和k值大小
        return ERROR;
    while(head->data!=1)//当表长为1是终止循环
    {
        if(flag%k==0)//删除节点条件
        {
            State=SList_Delete_Pos(head,Data,Pos);//删除节点
            Pos--;
        }
        if(Pos==head->data)
            Pos=0;
        Pos++;//位置移位
        flag++;
    }
    *Data=head->next->data;//返回剩余元素
    return OK;
}//约瑟夫问题

int SList_Read(SList head)
{
    FILE *fp;
    SList p=head,q;
    int i=1;
    if((fp=fopen("Single_LinkList.txt","r"))==NULL)//打开文件并判断是否成功
        exit(INFEASIBLE);
    SList_Clear(head);//清空表
    if((fscanf(fp,"%d",&head->data))==EOF)//判断文件是否为空
        return ERROR;
    for(i=1;i<=head->data;i++)
    {
        q=(SList)malloc(sizeof(SLinkList));//申请节点空间并判断是否成功
        if(!q)
            exit(INFEASIBLE);
        fscanf(fp,"%d",&q->data);//读取节点元素
        p->next=q;
        p=q;//插入节点元素
    }
    p->next=NULL;//尾节点指针域置空
    fclose(fp);
    return OK;
}//读取数据

int SList_Save(SList head)
{
    FILE *fp;
    SList p=head->next;
    if((fp=fopen("Single_LinkList.txt","w"))==NULL)//打开文件并判断是否成功
        exit(INFEASIBLE);
    if(!p)//判断是否为空表
        return ERROR;
    fprintf(fp,"%0d ",head->data);//写入表长
    while(p)
    {
        fprintf(fp,"%0d ",p->data);//写入节点元素
        p=p->next;//指针移位
    }
    fclose(fp);
    return OK;
}//保存数据

int menu()
{
    int result;
    while(1)//打印菜单
    {
        system("cls");
        printf("*****************菜单*****************\n");
        printf("01.初始化链表        02.按位置插入\n");
        printf("03.按位置删除        04.按元素删除\n");
        printf("05.按位置替换        06.按元素替换\n");
        printf("07.按位置查找        08.按元素查找\n");
        printf("09.查看表元素        10.查看表长\n");
        printf("11.清空表      12.销毁表\n");
        printf("13.约瑟夫环     14.保存数据\n");
        printf("15.读取数据     00.退出程序\n");
        printf("**************************************\n");
        printf("请选择:");
        while(scanf("%d",&result)!=1)//判断输入是否为1
        {
            fflush(stdin);
            continue;
        }
        if(0<=result&&result<=15)//判断输入是否合法,合法则退出并返回
            break;
    }
    return result;

}//菜单函数

int main()
{
    SList head;
    int State,Data,data,Pos,N,result;
    int Position[LIMIT];
    while(1)
    {
        result=menu();
        switch(result)
        {
        case 1:
            system("cls");
            printf("初始化链表:\n");
            State=SList_Init(&head);
            if(State==ERROR)
                printf("初始化失败!\n");
            else
                printf("初始化成功!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 2:
            system("cls");
            printf("按位置插入:\n");
            printf("请输入插入位置(1-%d):",head->data+1);
            scanf("%d",&Pos);
            printf("请输入插入元素:");
            scanf("%d",&Data);
            State=SList_Insert(head,Data,Pos);
            if(State==ERROR)
                printf("插入位置错误!\n");
            else
                printf("插入成功!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 3:
            system("cls");
            printf("按位置删除:\n");
            printf("请输入删除位置(1-%d):",head->data);
            scanf("%d",&Pos);
            State=SList_Delete_Pos(head,&Data,Pos);
            if(State==ERROR)
                printf("删除位置错误!\n");
            else
            {
                printf("删除成功!\n");
                printf("被删除元素为:%d\n",Data);
            }
            printf("按任意键继续......\n");
            getch();
            break;
        case 4:
            system("cls");
            printf("按元素删除:\n");
            printf("请输入删除元素:");
            scanf("%d",&Data);
            State=SList_Delete_Elem(head,Data);
            if(State==ERROR)
                printf("目标元素不存在!\n");
            else
                printf("删除成功!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 5:
            system("cls");
            printf("按位置替换:\n");
            printf("请输入替换位置(1-%d):",head->data);
            scanf("%d",&Pos);
            printf("请输入替换元素:");
            scanf("%d",&Data);
            State=SList_Replace_Pos(head,&Data,Pos);
            if(State==ERROR)
                printf("替换位置错误!\n");
            else
            {
                printf("替换成功!\n");
                printf("目标位置元素为:%d\n",Data);
            }
            printf("按任意键继续......\n");
            getch();
            break;
            case 6:
            system("cls");
            printf("按元素替换:\n");
            printf("请输入替换前元素:");
            scanf("%d",&data);
            printf("请输入替换后元素:");
            scanf("%d",&Data);
            State=SList_Replace_Elem(head,Data,data);
            if(State==ERROR)
                printf("目标元素不存在!\n");
            else
                printf("替换成功!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 7:
            system("cls");
            printf("按位置查找:\n");
            printf("请输入查找位置(1-%d):",head->data);
            scanf("%d",&Pos);
            State=SList_Find_Pos(head,&Data,Pos);
            if(State==ERROR)
                printf("查找位置错误!\n");
            else
                printf("目标位置元素为:%d\n",Data);
            printf("按任意键继续......\n");
            getch();
            break;
        case 8:
            system("cls");
            printf("按元素查找:\n");
            printf("请输入查找元素:");
            scanf("%d",&Data);
            State=SList_Find_Elem(head,Data,Position,&N);
            if(State==ERROR)
                printf("目标元素不存在!\n");
            else
            {
                printf("目标元素在表中的所有位置为:\n");
                for(Pos=0;Pos<=N-1;Pos++)
                    printf("%0d ",Position[Pos]);
                printf("\n");
            }
            printf("按任意键继续......\n");
            getch();
            break;
        case 9:
            system("cls");
            printf("查看表元素:\n");
            State=SList_Show(head);
            if(State==ERROR)
                printf("空表!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 10:
            system("cls");
            printf("查看表长:\n");
            SList_Show_Length(head,&Data);
            printf("表长为:%d\n",Data);
            printf("按任意键继续......\n");
            getch();
            break;
        case 11:
            system("cls");
            printf("清空表:\n");
            SList_Clear(head);
            printf("已清空!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 12:
            system("cls");
            printf("销毁表:\n");
            SList_Destroy(head);
            printf("已销毁!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 13:
            system("cls");
            printf("约瑟夫环:\n");
            printf("请输入约瑟夫环K值:");
            scanf("%d",&N);
            State=SList_Josephus(head,N,&Data);
            if(State==ERROR)
                printf("K值错误!\n");
            else
                printf("最终存留的元素为:%d\n",Data);
            printf("按任意键继续......\n");
            getch();
            break;
        case 14:
            system("cls");
            printf("保存数据:\n");
            State=SList_Save(head);
            if(State==ERROR)
                printf("空表!\n");
            else
                printf("保存成功!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 15:
            system("cls");
            printf("读取数据:\n");
            State=SList_Read(head);
            if(State==ERROR)
                printf("暂无数据!\n");
            else
                printf("读取数据成功!\n");
            printf("按任意键继续......\n");
            getch();
            break;
        case 0:
            printf("确定退出程序?Y/N\n");
            fflush(stdin);
            if(getchar()=='Y')
            {
                printf("谢谢使用!\n");
                exit(0);
            }
            printf("按任意键继续......\n");
            getch();
            break;
        }
    }
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值