从零开始学数据结构系列之第一章《单链表的基本操作》


单链表的基本操作

注意,后面的基本都是带有头节点的

不带头结点单向不循序链表:

在这里插入图片描述

创建一个单链表

​   对于每个链表结点,除了存放元素自身的信息外,还需要存放一个指向其后继的指针。

typedef struct Node
{ //定义单链表结点类型
	int data; //数据域,可以是别的各种数据类型,本文统一用int类型
	struct Node *next; //指针域
}Node;

初始化

​   通常会用头指针来标识一个单链表,头指针为NULL时表示一个空表。但是,为了操作方便,会在单链表的第一个结点之前附加一个结点,称为头结点

​     头结点的数据域可以不设任何信息,也可以记录表长等信息。

​     头结点的指针域指向线性表的第一个元素结点。如下图所示:

在这里插入图片描述
头结点和头指针的区分:

​   不管带不带头结点,头指针始终指向单链表的第一个结点,而头结点是带头结点的单链表中的第一个结点,结点内通常不存储信息。

注意,以下的都是包含了头节点的

​   那么单链表的初始化操作就是申请一个头结点,将指针域置空。

/* 申请内存 */
/* 列表初始数据为0 */
/* 列表的下一项指向空 */
Node* InitList()
{
	Node* list = (Node*)malloc(sizeof(Node));  
    list -> data = 0;   
    list -> next = NULL;
    return list;
}

头插法

  所谓头插法建立单链表是说将新结点插入到当前链表的表头,即头结点之后。如图所示:

在这里插入图片描述
  头插法建立的单链表中结点的次序和输入数据的顺序不一致,是相反的。若希望两者的顺序是一致的,则可采用尾插法建立单链表。

可以理解为:

1 2 3 中要用头插法插入一个数字4,那么插入后的排序应该是4 1 2 3

/* 
申请内存 
插入数据为形参中待插入的数据
更新指向第一项的位置
更新原先列表的下一项指向待插入数据
总数据数++
*/
void headInsert(Node* list, int data)
{
    Node* node = (Node*)malloc(sizeof(Node));  
    node -> data = data;
    node -> next = list -> next;           
    list -> next = node;
    list -> data++;
}

尾插法

​   所谓尾插法建立单链表是说将新结点插入到当前链表的表尾,即头结点之后。如图所示:
在这里插入图片描述
可以理解为:

​   0 1 2 3 中要用头插法插入一个数字4,那么插入后的排序应该是 0 1 2 3 4

/* 
申请内存 
插入数据为形参中待插入的数据
待插入的指针的下一项指向NULL
找到列表的最后一项,然后当list -> next为NULL的时候退出while
更新原先列表的下一项 指向 Node
总数据数++
*/
void tailInsert(Node* list, int data)
{
    Node* head = list;
    Node* node = (Node*)malloc(sizeof(Node));  
    node -> data = data;
    node -> next = NULL;
    list = list -> next;
    while(list -> next)
    {
        list = list -> next;
    }
    list -> next = node;
    head ->data ++;  
}

删除操作

将单链表的第 i 个结点删除。

可以理解为:

​   0 1 2 3 4中要删除一个数字2,那么插入后的排序应该是 0 1 3 4

​   0 1 2 2 3 4中要删除一个数字2,那么插入后的排序应该是 0 1 2 3 4

/* 
先保存当先列表与列表的第一项的位置
然后找到待删除的地点
将列表的下一项 指向 列表下一项的下一项
释放列表的下一项的内存
之后将指针都后移一个
之后列表数据总数相减
*/
void delete(Node* list, int data) 
{
    Node* preNode = list;
    Node* node = list -> next;
    while(node)
    {
        if(node -> data == data) 
        {
            preNode -> next = node->next;
            free(node);
            list -> data --;
           	break;
        }
        preNode = node;
        node = node -> next;
    }    
}

打印

void printfList(Node* list)
{
    list = list -> next;
    while(list)
    {
        printf("%d",list -> data);
        list = list -> next;
    }
    printf("\n");
}

总代码

#include <stdio.h>
#include "stdlib.h"

typedef struct Node
{
	int data;
	struct Node *next;
}Node;

Node* InitList()
{
	Node* list = (Node*)malloc(sizeof(Node));  
    list -> data = 0;   
    list -> next = NULL;
    return list;
}

void headInsert(Node* list, int data)
{
    Node* node = (Node*)malloc(sizeof(Node));  
    node -> data = data;
    node -> next = list -> next;	
    list -> next = node;
    printf("headInsert中list -> next的地址为%p\r\n",list -> next);
    list -> data++;
}

void tailInsert(Node* list, int data)
{
    Node* head = list;
    Node* node = (Node*)malloc(sizeof(Node));  
    node -> data = data;
    node -> next = NULL;
    list = list -> next;
	printf("tailInsert中list -> next的地址为%p\r\n",list -> next);
    while(list -> next)
    {
        list = list -> next;
    }
    list -> next = node;
    head ->data ++;  
}

void delete(Node* list, int data) 
{
    Node* preNode = list;
    Node* node = list -> next;
    while(node)
    {
        if(node -> data == data) 
        {
            preNode -> next = node->next;
            free(node);
            node=NU
            list -> data --;
           	break;
        }
        preNode = node;
        node = node -> next;
    }
    
}

void printfList(Node* list)
{
    list = list -> next;
    while(list)
    {
        printf("%d",list -> data);
        list = list -> next;
    }
    printf("\n");
}


void main()
{
	Node* list = InitList();
	headInsert(list,1);
	headInsert(list,2);
	headInsert(list,3);
	headInsert(list,3);
	tailInsert(list,4);
	tailInsert(list,5);
	tailInsert(list,6);
	printfList(list);
	delete(list,3);
	printfList(list);
}

在这里插入图片描述
在这里插入图片描述

往期回顾

1.【第一章】《线性表与顺序表》
2.【第一章】《单链表》
3.【第一章】《单链表的介绍》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值