03_单链表及其基本操作

一、什么是单链表
用自己得到话来说:
    1、全称是 单方向链表
    2、它是由节点组成的,每个节点包括两个部分,数据域 和 指针域
            数据域:存储的数据元素
            指针域:存储的是另外一个节点在内存中的地址
二、单链表的定义
    typedef struct node{
        ElemType data; //数据域
        struct node* next; //指针域
    }Node, * LinkedList;
三、单链表中必备的函数
1、判断单链表是否为空

2、求单链表长度

3、判断addr(代表第几个元素的位置)是否在单链表中

4、定位到addr的前一个元素

5、新建一个节点

6、插入一个节点

7、删除一个节点
//1、判断链表是否为空
bool isEmpty(LinkedList head) {
    if (!head->next)
        return true; //为空
    return false; //不为空
}
//2、求链表长度
int length_list(LinkedList head){
    Node * temp = head;
    int length = 0;
    while(temp->next){
        length++;
        temp = temp->next;
    }
    return length;
};
//3、判断addr是否在链表中
bool isBetween(LinkedList head, int addr){
    int length = length_list(head);
    if(addr<1 || addr>length)
        return false; //在区间中
    return true;//不在区间中
}
//4、定位到addr的前一个元素
Node * locat_before_addr(LinkedList head, int addr){
    Node * temp = head;
    for (int i = 1; i < addr ; ++i) {
        temp = temp->next;
    }
    return temp;
}
//5、新建一个节点
Node * new_node(ElemType elem, Node * next){
    Node * pNew = (Node *)malloc(sizeof(Node));
    if(!pNew){
        printf("创建节点失败!\n");
        exit(1);
    }
    pNew->data = elem;
    pNew->next = next;
    return pNew;
}
//6、插入节点
void insert_elem(Node * before_node, Node * after_node){
    after_node->next = before_node->next;
    before_node->next = after_node;
}

//7、删除节点
void delete_elem(Node * before_node, Node * after_node){
    Node * temp = after_node;
    before_node->next = after_node->next;
    free(temp);
四、单链表中的基本操作
1、单链表的初始化
//初始化单链表,一般是带有头节点的,因为方便以后对链表中的元素进行操作
LinkedList init_list(){

    Node * head = (Node *)malloc(sizeof(Node)); //初始化头节点
    if(!head){
        printf("初始化头节点失败!\n");
        return Error;
    }
    head->next = NULL;
    return head;
}

/*
 * 只要是创建(初始化)一个节点,
 * 需要先判断节点是否为空,
 * 然后再将节点中的数据项进行初始化
 *      数据域有元素可以赋值的就赋值
 *      指针域统一设置为NULL
 **/
2、单链表中插入元素
(1)在某个节点之后插入元素
(2)在某个节点之前插入元素
(3)在链表中指定位置插入元素
//1、在某个节点后面插入元素
Status insert_after_node(Node * node, ElemType elem){

    //1 创建新的节点
    Node * pNew = new_node(elem,NULL);

    //2 插入新的节点
    insert_elem(node,pNew);
    return Ok;
}
//2 在某个节点之前插入元素
Status insert_before_node(LinkedList head, Node * node, ElemType elem){

    Node * temp = head;

    //1、首先找目标节点的前驱节点
    while(temp){
        if(temp->next == node)
            break;
        temp = temp->next;
    }

    //2、创建新的节点
    Node * pNew = new_node(elem, NULL);

    //3、插入节点
    insert_elem(temp, pNew);

    return Ok;
}
//3、在链表中指定位置插入元素
Status insert_list(LinkedList head, int addr, ElemType elem){
    Node * temp = locat_before_addr(head, addr);
    insert_after_node(temp,elem);
    return Ok;
}
3、单链表中遍历元素
void traverse_list(LinkedList head){
    Node * temp = head->next;
    while(temp){
        printf("%d\n",temp->data);
        temp = temp->next;
    }
    printf("\n");
}

4、单链表中删除元素
(1)删除指定位置的元素
(2)删除指定元素值的元素
//1 删除指定位置的元素
Status delete_by_addr(LinkedList head, int addr){

    if (!isBetween(head,addr)){
        printf("要删除的元素不在区间中!\n");
        return Error;
    }

    Node * before_node =  locat_before_addr(head, addr);
    delete_elem(before_node,before_node->next);
    return Ok;
}

//2 删除指定元素
Status delete_by_elem(LinkedList head, ElemType elem){

    Node * temp = head;

    Node * before_node = head;

    while (temp){
        before_node = temp;
        temp = temp->next;

        if (temp == NULL)
            return Error;

        if (temp->data == elem)
            break;
    }

    delete_elem(before_node,temp);

    return Ok;
}

5、单链表中查找元素
(1)通过addr返回某个元素的值
(2)通过指定元素的值返回addr
//1 按照addr查找链表中的元素
Status search_by_addr(LinkedList head, int addr, ElemType * target_data){
    if (!isBetween(head,addr)){
        printf("地址不在链表中!\n");
        return Error;
    }
    Node * before_node = locat_before_addr(head, addr);
    * target_data = before_node->next->data;
    return Ok;
}
//2 按照元素返回addr
int search_by_elem(LinkedList head, ElemType elem){
    Node * temp = head;

    int addr = 0;
    for (int i = 0; i < length_list(head); ++i) {
        temp = temp->next;
        if (temp == NULL){
            break;
        }
        if (temp->data == elem){
            addr = i+1;
            break;
        }
    }

    return addr;
}
五、补充头文件
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
#define ElemType int
#define Status bool
#define Ok 1
#define Error 0

typedef struct node{
    ElemType data; //数据域
    struct node* next; //指针域
}Node, * LinkedList;
六、总结
1、将单链表中必备函数给背下来,当然不是背代码
2、熟练掌握对单链表的五种基本操作,及其变种函数
3、个人建议不要将所有的操作放在一个.c或.cpp文件中,而是通过.h文件进行函数调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_43876924

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值