单链表的基本操作

一、实验目的:

1、复习C语言程序设计中的知识。

2、掌握线性表的链式存储结构的表示和实现方法。

3、掌握单链表基本操作的算法实现。

 

二、实验内容:

1.建立单链表。

2.在单链表上实现插入、删除和查找等操作。

 

三、实验要求:

   编写实现单链表的基本算法(初始化、查找、插入、删除等)的函数,并在此基础上设计一个主程序完成如下功能:

   ⑴初始化整型单链表H;

   ⑵采用尾插法建立单链表H,如(a,b,c,d,c);

   ⑶输出单链表H的长度;

   ⑷输出单链表H的第i个元素,如输出单链表H的第3个元素;

   ⑸输出给定元素的位置,如输出元素a的位置;

   ⑹在第i个元素前插入给定元素,如在第4个元素前插入元素f

   ⑺删除单链表H的第i个元素,如删除单链表H的第3个元素。

   输出单链表

代码如下:(注:需要运行功能a再执行其他功能)

#include<stdio.h>
#include<stdlib.h >
typedef int elemtype;            //节点的数据类型,设为整型
typedef struct node                //定义单链表节点类型
{
    elemtype data;                //节点的数据域
    struct node *next;            //节点的指针域
}LinkList;                        //单链表的类型名为 LinkList
LinkList *head;                    //head 是指向单链表类型LinkList的指针变量
//初始化单链表
LinkList *Init_LinkList()
{
    LinkList *head;                        //
    head = (LinkList*)malloc(sizeof(LinkList)); //生成头结点指针
    if (head == NULL)                            //如果申请空间失败,返回空指针
    {
        printf("初始化失败!\n");
        return 0;
    }
    else
    {
        printf("初始化成功!\n");
        return head;
    }
}
//尾插法创建带头结点单链表的函数
LinkList *Create_LinkListR(LinkList*head)                    //尾插法创建带头结点单链表的函数
{
    elemtype ix;                                //
    LinkList *p, *tail;                    //*head,tail分别为头指针和尾指针
    head->next = NULL;                            //置头结点指针域为空
    tail = head;                                //尾指针域指向头结点
    printf("请输入数据直到输入0结束:");        //
    scanf("%d", &ix);                            //输入第一个数据
    while (ix != 0)                                //输入数据,0为结束标志
    {
        p = (LinkList*)malloc(sizeof(LinkList));//生成新结点
        if (p == NULL)                            //如果申请空间失败,返回主调函数
        {
            printf("新结点申请空间失败,无法继续建立单链表!\n");
            return head;
        }
        p->data = ix;                            //为新结点数据域赋值
        tail->next = p;                            //修改尾结点指针域
        tail = p;                                //修改尾指针
        tail->next = NULL;                        //将尾结点的指针域置为空
        scanf("%d", &ix);                        //读入下一个数据
    }
    printf("单链表建立成功!\n");
    return head;                                //返回头结点指针

}
//单链表的遍历
int Print_LinkList(LinkList*head)                //单链表的遍历
{
    LinkList *p = head->next;                    //
    if (p == NULL)                                //链表为空,返回值为0
    {
        printf("单链表为空!\n");
        return 0;                                //
    }
    while (p != NULL)                            //当前结点不为空
    {
        printf("%d\n", p->data);                //输出当前结点的数据
        p = p->next;                            //移动指针指向下一个结点
    }
    return 1;
}
//单链表的长度
void LinkList_Length(LinkList*head)                //单链表的长度
{
    LinkList*p = head;                            //p指向头结点
    int j = 0;                                    //
    while (p->next != NULL)                        //
    {
        p = p->next;                            //p指向的是第j个结点
        j++;                                    //
    }
    printf("单链表长度为:%d\n", j);
}
//单链表查找,按序号查找
LinkList *GetData_LinkList(LinkList *head/*, int i*/)    //单链表查找,按序号查找
{
    LinkList *p;                                    //
    int i;
    int j = 0;                                        //
    printf("需要查找的元素为第几个?\n");
    scanf("%d", &i);
    if (i <= 0)                                        //指定的位置非法时返回NULL
    {
        printf("你所输入的元素位置非法!\n");
        return NULL;                                //
    }
    p = head;                                        //
    while (p->next != NULL&&j < i)                    //不是目标结点且还有后继结点时继续查找
    {
        p = p->next;                                //
        j++;                                        //
    }
    if (i == j)                                        //找到目标结点,返回当前指针
    {
        printf("查找的元素为:%d\n",p->data);
        return p;                                    //
    }
    else
    {
        printf("未找到目标结点!\n");
        return NULL;                                //未找到目标结点,返回NULL
    }
}
LinkList *GetData_LinkList_A(LinkList *head, int i)
{
    LinkList *p;                                    //
    int j = 0;                                        //
    if (i <= 0)                                        //指定的位置非法时返回NULL
    {
        printf("你所输入的元素位置非法!\n");
        return NULL;                                //
    }
    p = head;                                        //
    while (p->next != NULL&&j < i)                    //不是目标结点且还有后继结点时继续查找
    {
        p = p->next;                                //
        j++;                                        //
    }
    if (i == j)                                        //找到目标结点,返回当前指针
    {
        /*printf("查找的元素为:%d\n", p->data);*/
        return p;                                    //
    }
    else
    {
        printf("未找到目标结点!\n");
        return NULL;                                //未找到目标结点,返回NULL
    }
}
//单链表的查找,按值查找
LinkList *Search_LinkList(LinkList *head/*, elemtype key*/)//单链表的查找,按值查找
{
    LinkList *p;
    elemtype key;
    int j = 0,i=1;
    printf("请输入所需查找元素的值:");
    scanf("%d", &key);
    p = head->next;                                        //指针指向首结点
    while (p != NULL)                                    //
    {
        if (p->data != key)                                //
        {
            p = p->next;                                //取下一个结点,继续查找
            i++;
        }
        else        
        {
            printf("所查找的元素位置为:%d\n", i);
            j = 1;
            break;                                        //找到结点key,退出循环
        }
    }
    if (j == 0)
    {
        printf("链表中没有该元素。\n");
    }
    return 0;
    /*return p;*/                                            //返回找到的结点指针域或未找到时的NULL
}
//单链表的插入 后插运算
void InserAfter_LinkList(LinkList *p, LinkList *s)        //单链表的插入 后插运算
{
    s->next = p->next;                                    //新结点连入链表
    p->next = s;                                        //修改前趋结点的指针域
}
//单链表的插入,前插运算
void InserBefore_LinkList(LinkList *head/*, LinkList *p, LinkList *s*/)//单链表的插入,前插运算
{
    LinkList *q;                                                    //
    LinkList *p;
    LinkList *s;
    q = head;                                                        //
    printf("在哪个元素前插入元素?\n");
    scanf("%d", p->data);
    printf("请输入所要插入的元素:%d", s->data);

    while (q->next != p)                                            //从头结点开始搜索结点p的前驱结点
    {
        q = q->next;                                                //
    }
    s->next = p;                                                    //修改相应结点的指针域
    q->next = s;                                                    //修改相应结点的指针域
    printf("插入成功!\n");
}
//单链表的插入,在指定序号前插入运算
int InserNo_LinkList(LinkList *head/*, LinkList *s, int i*/)    //单链表的插入,在指定序号前插入运算
{
    LinkList *p, *s;
    int i;
    s = (LinkList*)malloc(sizeof(LinkList));
    printf("在第几个元素前插入元素?\n");
    scanf("%d", &i);
    printf("插入的元素为:");
    scanf("%d", &s->data);
    if (i <= 0)
    {
        p = NULL;
    }
    else if (i == 1)
    {
        p = head;
    }
    else
    {
        p = GetData_LinkList_A(head, i - 1);                    //搜索第i-1个结点
    }
    if (p == NULL)
    {
        printf("你所输入的位置不合法!\n");
        return 0;                                            //不存在第i个位置的结点
    }
    else
    {
        InserAfter_LinkList(p, s);                            //调用后插函数
        printf("插入成功!\n");
        return 1;
    }
}
//单链表的删除 删除后继结点
int DeleteAfter_LinkList(LinkList *p)    //单链表的删除 删除后继结点 删除p的后继结点,成功返回1,否则返回0
{
    LinkList *r;
    if (!p)
    {
        return 0;
    }
    r = p->next;
    if (!r)
    {
        return 0;
    }
    p->next = r->next;                    //将结点r从链表上摘除
    free(r);                            //释放结点占用的内存空间
    return 1;    
}
//单链表的删除 删除指定结点本身 
int DeleteNode_LinkList(LinkList *head, LinkList *p)//单链表的删除 删除指定结点本身 
{
    LinkList *r;
    if (p->next != NULL)                            //若p有后继结点
    {
        p->data = p->next->data;                    //将后继结点的数据写入当前结点的数据域
        return (DeleteAfter_LinkList(p));            //删除p的后继结点
    }
    else
    {
        r = head;
        while (r->next != p)                        //搜索p的前驱结点
        {
            r = r->next;
        }
        return (DeleteAfter_LinkList(r));            //删除p的后继结点
    }
}
//单链表的删除 删除指定位置的结点
int DeleteNo_LinkList(LinkList *head/*, int i*/)    //单链表的删除 删除指定位置的结点 删除成功返回1,否则返回0
{
    LinkList *p, *r;
    int i;
    printf("删除第几个元素?\n");
    scanf("%d", &i);
    if (i <= 0)
    {
        p = NULL;
    }
    else if (i == 1)
    {
        p = head;
    }
    else
    {
        p = GetData_LinkList_A(head, i - 1);        //搜索第i-1个结点
    }
    if (p == NULL)                                //不存在第i个结点,删除失败
    {
        return 0;
    }
    else                                        //找到第i-1个结点
    {
        r = p->next;
        if (r == NULL)                            //第i个结点不存在,删除失败
        {
            return 0;
        }
        p->next = r->next;                        //删除指定结点
        printf("删除成功!\n");
        free(r);
        return 1;
    }
}
//置空表
LinkList *SetNull_LinkList(LinkList *head)        //置空表
{
    while (head->next)
    {
        DeleteAfter_LinkList(head);                //依次删除每个结点
    }
    printf("单链表置空成功!\n");
    return head;
}
//菜单界面
void menu()
{
    system("cls");
    printf("\n");
    printf("\t\t---------------欢迎使用单链表的基本操作------------------\n");
    printf("\t\t|\t\t a 初始化单链表               \t\t|\n");
    printf("\t\t|\t\t b 采用尾插法建立单链表       \t\t|\n");
    printf("\t\t|\t\t c 输出单链表的长度           \t\t|\n");
    printf("\t\t|\t\t d 输出单链表的第i个元素      \t\t|\n");
    printf("\t\t|\t\t e 输出给定的元素的位置       \t\t|\n");
    printf("\t\t|\t\t f 在第i个元素前插入给定的元素\t\t|\n");
    printf("\t\t|\t\t g 删除单链表的第i个元素      \t\t|\n");
    printf("\t\t|\t\t h 输出单链表                 \t\t|\n");
    printf("\t\t|\t\t i 置空单链表                 \t\t|\n");
    printf("\t\t|\t\t j 退出系统                   \t\t|\n");
    printf("\t\t---------------------------------------------------------\n");
    printf("\t\t请选择(a-j):");
}

int main()
{
    LinkList *head;
    int quit=0;
    char select;
    while (1)
    {
        menu();            //调用子函数
        scanf("%c", &select);
        switch (select)
        {
            case 'a': head =Init_LinkList(); break;//初始化单链表
            case 'b': Create_LinkListR(head); break; //采用尾插法建立单链表
            case 'c': LinkList_Length(head); break; //输出单链表的长度
            case 'd': GetData_LinkList(head); break;//输出单链表的第i个元素  按序号查找
            case 'e': Search_LinkList(head); break;//输出给定的元素的位置  按值查找
            case 'f': InserNo_LinkList(head); break;//在第i个元素前插入给定的元素
            case 'g': DeleteNo_LinkList(head); break;//删除单链表的第i个元素  删除指定位置的结点
            case 'h': Print_LinkList(head); break;//输出单链表
            case 'i': SetNull_LinkList(head); break;//置空单链表
            case 'j': quit = 1; break;
            default:printf("请输入a~j之间的数字\n"); break;
        }
        if (quit == 1)
        {
            break;
        }
        printf("按任意键返回主菜单!\n");
        getchar();                //提取到缓冲区中的回车键
        getchar();                //起到暂停的作用
        printf("程序结束!\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值