数据结构之线性单链表的基本使用(创建插入查找删除)

1.单链表创建

单链表的创建有两种,分别是头插法和尾插法,头插法为逆序排序,尾插法为顺序排序,简称“头逆尾顺”。

1.1 头插法

每次插入的新结点均将作为新的第一个数据节点,即后来居上。
创建代码如下,该创建方法将包含头结点:

#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct Lnode{
    ElementType data;
    struct Lnode *next;
}LNode, *Linklist;

Linklist Create_list_head(Linklist head){  //头插法(含头结点)
    head = (Linklist)malloc(sizeof(LNode)); //为头指针开辟内存空间
    LNode * node = NULL;   //定义工作指针
    int count = 0;         //定义创建的结点数量
    head->next = NULL;
    scanf("%d", &count);
    for (int i = 0; i < count; i++){
        node = (LNode *)malloc(sizeof(LNode)); //创建新结点
        node->data = i;   //为新结点的数据域赋值
        node->next = head->next; //将新结点插入到头结点和第一个结点之间
        head->next  = node;  //更新头结点的next值为新结点
    }
    return head;
}

1.2 尾插法

每次插入的新结点均将添加到数据的尾部。
创建代码如下,该创建方法将包含头结点:

#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct Lnode{
    ElementType data;
    struct Lnode *next;
}LNode, *Linklist;

Linklist Create_list_tail(Linklist head){
	//尾插法(含头结点)
    head = (Linklist)malloc(sizeof(LNode));
    Linklist node = NULL;
    Linklist end = NULL;
    head->next = NULL;  //若没有后续结点,则将next值为null
    end = head; //若没有后续结点,则记录尾结点为头结点。
    int count = 0;  //结点个数
    scanf("%d", &count);
    for (int i = 0; i < count; i++){
        node = (LNode *)malloc(sizeof(LNode));  //为新结点开辟空间
        node->data = i;      //为新的结点数据域赋值
        end->next = node;   // 将新结点的值给上一个结点的next
        end = node;         //将新结点标记为尾结点
    }
    end->next = NULL;      //将尾结点的next值赋为NULL
    return head;
}

2.单链表的查找

2.1 按序号查找

在带头节点的单链表L中查找序号为i(1<=i<=n)的元素

bool Get_elem_l(Linklist L, int i){ 
    //在带头节点的单链表L中查找序号为i(1<=i<=n)的元素
    ElementType e;
    LNode * p;
    p = L->next;
    int j = 1;
    while (p && j < i){  
        p = p->next;
        j++;
    }
    if (!p || j > i) return false;
    e = p->data;
    printf("元素已经找到,为:%d\n",e);
    return true;
}

2.2 按值查找

在带头结点的单链表L中查找序号为i(1<=i<=n)的元素

bool Get_elem_l(Linklist L, int i){ 
    //在带头结点的单链表L中查找序号为i(1<=i<=n)的元素
    ElementType e;
    LNode * p;
    p = L->next;
    int j = 1;
    while (p && j < i){  
        p = p->next;
        j++;
    }
    if (!p || j > i) return false;
    e = p->data;
    printf("元素已经找到,为:%d\n",e);
    return true;
}

3.插入元素

在带头结点的单链表中的第i(1<=i<=n)个位置插入数据元素e

bool List_insert(Linklist L, int i, ElementType e){
    //在带头结点的单链表中的第i(1<=i<=n)个位置插入数据元素e 
    LNode * p = L;
    int j = 0;
    while (p && j < i -1) {
        p = p->next;
        j++;
    }
    if (!p || j > i - 1) return false;
    LNode * new;
    new = (LNode *)malloc(sizeof(LNode));
    new->data = e;
    new->next = p->next;
    p->next = new;
    return true;
}


4.删除元素

4.1 按位序删除

在单链表L中删除第i(1<=i<=n)个数据元素

bool List_delete_by_index(Linklist L, int i){
    //在单链表L中删除第i(1<=i<=n)个数据元素,此方法未考虑输入参数i大于链表元素个数的情况。
    LNode * p = L;
    ElementType e;
    int j = 0;
    while(p && j < i - 1){
        p = p->next;
        j++;
    }
    if (!(p->next) || j > i - 1) return false;
    LNode * q = p->next;
    p->next = q->next;
    e = q->data;
    printf("删除了位序为%d,其值为%d\n", i, e);
    free(q);
    return true;
}

4.2 按值删除

在单链表L中删除第1个值为e的数组元素

bool List_delete_by_v(Linklist L, ElementType e){
    LNode * p = L, * q = p->next;
    while (q != NULL && q->data != e){
        p = q;
        q = q->next;
    }
    if (!q) {  // 此处若q指针为NULL,则说明找到了末尾仍未找到
        printf("删除元素%d不存在!\n", e);
        return false;
    }
    else{
        p->next = q->next;
        free(q);
        printf("删除元素%d成功!\n",e);
        return false;
    }
}

5.访问链表中的所有元素

输出一个带头结点链表的所有元素的值。

void print_list(Linklist L){
    //访问单链表L的所有元素
    LNode * p;
    p = L->next;
    while (p){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

6.与顺序表的比较

链表相比较于顺序表的主要优势如下:

  • 删除指定元素时,无需对元素进行移动;
  • 插入指定元素时,无需对元素进行移动。

链表相比较于顺序表的缺点如下:

  • 访问某个位置的数据元素,必须要使用到循环;
  • 交换元素位置时,较为麻烦。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

theskylife

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

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

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

打赏作者

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

抵扣说明:

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

余额充值