C语言实现数据结构单链表的相关操作

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define FLAG -1    //停止输入的标志
typedef struct Node
{
    int data;
    struct Node * next;
}LNode,*LinkList;

void show_List1(LinkList L);
void CreateLinkList1(LinkList L);
void CreateLinkList2(LinkList L);
LNode *GetLinkList(LinkList L,int i);
LNode *LocationLinkList(LinkList L,int x);
void InsertLinkList(LinkList L,int i,int x);
void DeleteLinkList(LinkList L,int i);
int LengthLinkList(LinkList L);
void reverse(LinkList L);
void DelLink(LinkList L,int min,int max);
LinkList MergeList(LinkList La,LinkList Lb);

void main()
{
    //创建头指针指向头结点
    LinkList L = (LNode *)malloc(sizeof(LNode));//La,Lb,Lc;

    /*La = (LNode *)malloc(sizeof(LNode));
    Lb = (LNode *)malloc(sizeof(LNode));
    Lc = (LNode *)malloc(sizeof(LNode));*/
    CreateLinkList2(L);
    show_List1(L);
    DelLink(L,4,8);
    show_List1(L);
    //La->next = Lb->next = Lc->next = NULL;
    //CreateLinkList1(L);
    /*printf("输入链表La:\n");

    printf("输入链表Lb;\n");
    CreateLinkList2(Lb);
    printf("合并后的链表:\n");
    Lc = MergeList(La,Lb);
    show_List1(Lc);*/
    //printf("\n%p",GetLinkList(L,2));//输出结点指针地址
    //printf("\n%p",LocationLinkList(L,2));//
   /* InsertLinkList(L,2,99);
    show_List1(L);
    DeleteLinkList(L,5);
    show_List1(L);
    printf("%d",LengthLinkList(L));*/
    /*reverse(L);
    printf("倒置后的链表:\n");
    show_List1(L);*/
    /*DelLink(L,3,7);
    printf("删除后的链表:\n");
    show_List1(L);*/
}
void show_List1(LinkList L)
{
    LinkList p = L->next;
    printf("%d",p->data);
    p = p ->next;
    while(p != NULL)
    {
        printf("->%d",p->data);
        p = p->next;
    }
    printf("\n");
}

void CreateLinkList1(LinkList L) //头插法   输出的是输入的逆序
{
    LinkList s;
    int x;
    scanf("%d",&x);
    while(x != FLAG)
    {
        /*s = L;
        s->data = x;
        L = (LNode *)malloc(sizeof(LNode));
        L->next = s;*/
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        s->next = L->next;
        L->next = s;

        scanf("%d",&x);
    }
}

void CreateLinkList2(LinkList L)  //尾插法  输出是输入的正序
{
    LinkList s,r;
    int x;
    scanf("%d",&x);
    r = L;    //没写闪退
    while(x != FLAG)
    {
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        //r->next = s;
        //s->next = r->next;   出错误的原因是r->next中已经是新节点的地址了,
        //再把新节点地址赋值给它的指针域,会导致自己不断的指自己 不断 33333

        //不妨先把r->next也就是NULL赋给新节点指针域,再将上一个指向新节点,这样就没问题了!
        //s->next = r->next;   //第一种写法
        r->next = s;

        r = s;
        scanf("%d",&x);
    }
    r->next = NULL;//第二种写法  先不管最后一个节点,最后再置为NULL
}

LNode *GetLinkList(LinkList L,int i)//按位置查找
{
    LinkList p;
    int j = 0;
    p = L;
    while(p != NULL && j < i)
    {
        p = p->next;
        j++;
    }
    return p;
}

LNode *LocationLinkList(LinkList L,int x) //按元素查找
{
    LinkList p;
    p = L->next;
    while(p != NULL && p->data != x)
    {
        p = p->next;

    }
    return p;
}

void InsertLinkList(LinkList L,int i,int x)
{
    LinkList p,s;
    p = GetLinkList(L,i-1);
    if(p == NULL)
    {
        printf("插入失败!");
        exit(1);//0 -1 1 一般0是正常退出  其他是异常退出
    }
    else
    {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        s->next = p->next;
        p->next = s;
    }
}

void DeleteLinkList(LinkList L,int i)//删除第i个位置  p需要指向第i-1个位置
{
    LinkList q,p;
    p = GetLinkList(L,i-1);
    if(p == NULL)
    {
        printf("删除失败!");
        exit(1);
    }
    else
    {
        if(p->next == NULL)
        {
            printf("删除失败!");
            exit(1);
        }
        else
        {
            q = p->next;
            p->next = p->next->next;
            free(q);
        }
    }
}
int LengthLinkList(LinkList L)
{
    int len = 0;
    LinkList p = L;
    while(p->next)
    {
        len++;
        p = p->next;
    }
    return len;
}

void reverse(LinkList L)
{
    //节点指针p q
    //先把p指向首节点,再将头结点的指针域置为空 这样就出现一个p指向首节点的链表
    //q指向与p相同的结点  然后p后移
    //头结点的指针域中永远存放的是上一个结点的地址
    //
    /*LinkList p,q;
    p = L->next;
    L->next = NULL;
    while(p)
    {
        q = p;//先将p赋值给q
        p = p->next; // p后移
        q->next = L->next; //
        L->next = q;
    }*/


    //设置了两个游标 p主要负责查看是否是最后一个元素 并且 将后面的元素串联起来
    LinkList p,q;
    p = L->next; //记录下后面的所有元素
    L->next = NULL;//方便设置第一个元素的指针域为0
    while(p) // 是p不是p->next的原因 在于p->next会使最后一个元素无法倒置
    {
        q = p;
        p = p->next;//这一步必须在 第三步的前面  否则将会失去后面的所有元素
        q->next = L->next; //头结点中的指针域永远记录上一个元素的地址
        L->next = q;//q当前所指元素指向上一个元素后 头结点记录下当前节点地址
    }
}

void DelLink(LinkList L,int min,int max)
{
    LinkList p,q,s;
    p = L->next;
    while((p != NULL) && (p->data <= min))
    {
        q = p;
        p = p->next;
    }
    while((p != NULL) && (p->data < max))
    {
        s = p;
        p = p->next;
        //删除结点
        //q->next = p;
        free(s);
    }
    q->next = p; //
}

LinkList MergeList(LinkList La,LinkList Lb)
{
    LinkList p,q,r,Lc;
    p = La->next;
    q = Lb->next;

    r = Lc = Lb;

    while(q&&p)
    {
        //p或者q中数据域小的那个应当让上一个结点指向
        //并且应当把r指向小的那个结点
        //进行完上叙操作后,数据域小的那个应当将p或者q后移
        if(p->data >= q->data)
        {
            r->next = q;
            r = r->next;
            q = q->next;
        }
        else
        {
            r->next = p;
            r = r->next;
            p = p->next;
        }

    }
    if(q)
    {
        //说明后面还有
        r->next = q;
    }
    else
    {
        r->next = p;
    }
    free(La);
    return Lc;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值