考研数据结构代码实现-单链表

特点:

  1. 链式存储的线性表,便于插入和删除,但不能随机存储(即根据一定的公式快速定位某个结点,只能从前往后遍历)
  2. 节点包括:任意元素类型的数据域、结点类型的指针。
  3. 最好设置一个头结点,这样对第一个结点操作与对其他结点操作一致,对空表的操作和对非空表的操作一致。

单链表结点的描述

typedef struct{
    int num;
    char data; //这两个都是数据域,也可以单独定义一个结构体将这两个数据域打包
    struct Lnode *next; //指针域,一个类型为Lnode的指针
}Lnode ,*LinkList; //定义一个类型为Lnode的指针--LinkList;

一个小小的突发状况:. 和 -> 的区别
先说结论:结构体用点,结构体指针用箭头。 现在编译器优化后,两者可以通用

  1. ".“直接读做"的”。
    ->读作"指向的结构体的”
  2. C需要显式区分直接访问与指针间接访问。

应试需要,简单记为,顺序表用 . ,单链表用 ->

参考资料:
代码显示
知乎大佬们的讨论

头插法插入单链表

-思路:

  1. 定义一个头结点,包括使用malloc函数给其分配空间
  2. 头结点初始指向空
  3. while语句接收数据,插入单链表
  4. 为待插入的结点分配空间
  5. 待插入结点获取数据
  6. 待插入的结点指针域指向下一个结点的数据域,上一个结点的指针域指向待插入结点的数据域。顺序很重要!不能颠倒
  7. 返回头结点
//头插法
LinkList LHead(LinkList &L){
    // 返回值类型为LinkList ,传入的参数:类型为LinkList的单链表,记得带 & 符号,因为会对原有数据修改
    Lnode *s; //一个Lnode类型的指针.这个是待插入指针
    int x; //接收传入的数据
    L=(LinkList)malloc(sizeof(Lnode)); //malloc函数给 头结点 分配初始空间,强制转换类型为Lnode;
    //将L理解为头结点即可,其实并没有什么变量是专门指这整张单链表.表示一整张单链表只需要一个头指针就够了
    L->next=NULL; //初始化头结点指向空
    scanf("%d",&x); //接收第一个传入数据
    while(x!=99){ //当输入99时才跳出循环,这样可以保证连续输入多个数据
        s=(Lnode*)malloc(sizeof(Lnode)); //给待插入结点分配空间,这样才能存数据
        s->data=x; //没有搞清哪个是待插入结点,哪个是待插入链表,晕了,这里就不会写了.解决:Line 19
        s->next=L->next;
        L->next=s;  //这两行顺序不能颠倒
        scanf("%d",x);
    }
    return L; //返回头结点
}

尾插法插入单链表

  1. 分配空间
  2. while接收输入
  3. 尾结点指向新结点
//尾插法
LinkList LTail(LinkList &L){
    L=(LinkList)malloc(sizeof(Lnode));
    Lnode *s,*r;
    int m;
    s=(Lnode *)malloc(sizeof(Lnode));
    printf("请输入尾插法要插入的数据\n");
    scanf("%d",&m);
    while(m!=99){
        s->data=m;
        r->next=s;
        r=s;
        scanf("%d",&m);
    }
    r->next=NULL;
    return r;
}

按序号查找

-思路:

  1. 设置j用来记录结点位置
  2. 头结点赋值给p
  3. 三种情况:一、i为0,返回头结点。二、i小于0,报错。三、i>0
  4. 第三种情况,while循环让p指针不断后移,直至j==i
LinkList LSearch(LinkList L,int i){
    int j=0;
    //Lnode p = (Lnode)malloc(sizeof(Lnode));
    Lnode *p=L->next;
    if(i==0)
        return L;
    if(i<0)
        return NULL;
    while(p&&j<i){
        p=p->next;
        j++;
    }
    return p;
    
}

按值查找

-思路:

  1. 头结点赋值给p
  2. while,直至p=null 或 找到
//按值查找
LinkList LSearch_(LinkList L,int x){
    Lnode *p=L->next;
    while(p!=NULL&&p->data!=x)
        p=p->next;
    return p;
}

按位置插入

-思路:

  1. 根据按位置查找获取待插入位置的前驱结点
  2. 类比头插法插入
//根据位置插入
LinkList LInsert(LinkList L,int i){
    Lnode *s=(Lnode)malloc(sizeof(Lnode));
    p=LSearch(LinkList L,int i-1);
    s->next=p->next;
    p->next=s;
}

删除

思路:

  1. 找到前驱结点
  2. 前驱结点的指针域跳过待删除的结点,这样逻辑上就删除了
  3. free释放被删除结点的空间,物理删除
//删除
LinkList LDelete(LinkList L){
    p=LSearch(L,i-1);
    q=p->next;
    p->next=q->next;
    free(q);
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值