数据结构笔记之链表

1.3 线性结构之链表

1.3.1 基础知识

一个数据域一个指针域
逻辑结构:链表是一个线性结构,由一系列结点(Node)组成,每个结点包含一个数据元素和一个指向下一个结点的指针(Pointer)。所有结点通过指针相连,形成一个链式结构。通常我们将链表中的第一个结点称为头结点
在这里插入图片描述data :数据域,存放结点的值。
next :指针域,存放结点的直接后继的地址。
物理结构:与数组不同,链表中的结点需要自行组织,向系统申请很多分散在内存各处的结点,每个结点都保存了当前结点的数据和下一个结点的地址(指针),通过指针将结点串成一串。
具体如下:
在这里插入图片描述
链表的分类:
链表又分为单链表、双链表、循环单链表、循环双链表和静态链表。
在这里插入图片描述
在这里插入图片描述
相关概念
n个结点离散分配,彼此通过指针相连,每个结点只有一个前驱结点,每个结点只有一个后续结点,头结点没有前驱结点,尾结点没有后续结点。确定一个链表我们只需要头指针,通过头指针就可以把整个链表都能推出来。

1.3.2优缺点

优点:

插入和删除操作效率高
动态扩展性能更好

链表不需要像数组那样预先指定固定的大小,而是可以随时动态的增长或缩小。
链表是真正的动态数据结构,不需要处理固定容量的问题

缺点:

查找慢

由于链表中的结点不是连续存储的,无法像数组一样根据索引直接计算出每个结点的地址。必须从头结点开始遍历链表,直到找到目标结点,这导致了链表的随机访问效率较低。

额外的存储空间

链表的每个结点都需要存储指向下一个结点的指针,这会占用额外的存储空间。所以,相比于数组,链表需要更多的内存空间来存储相同数量的数据元素。

1.3.3 功能定义

初始化链表
void initLinkedList(LinkedList *list)
返回链表的长度
size_t getLength(const LinkedList *list)
在指定位置插入元素
void insertAt(LinkedList *list, size_t index, int element)
在末尾插入元素
void insertEnd(LinkedList *list, int element)
删除指定位置的元素并返回被删除的元素
int deleteAt(LinkedList *list, size_t index)
删除末尾元素
int deleteEnd(LinkedList *list)
获取指定位置的元素
int getElementAt(const LinkedList *list, size_t index)
修改指定位置的元素
void modifyAt(LinkedList *list, size_t index, int newValue)
释放链表内存

| void destroyLinkedList(LinkedList *list)

1.3.4 代码实现

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

/**
 * 自定义链表结构
*/

//定义存储数据的结构体

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

//定义一个虚拟头节点
typedef struct 
{
    int size;       //记录单链表中存储数据的个数
    Node *next
}LinkedList;

//明确:在包含虚拟头节点的情况下:首个保存数据的节点的索引为0



// 初始化链表
void initLinkedList(LinkedList *list){
    //初始化LinkedList内部的成员
    list->size = 0;
    list->next = NULL;

}
// 返回链表的长度
size_t getLength(const LinkedList *list){

    return list->size;


}
// 在指定位置插入元素
void insertAt(LinkedList *list, size_t index, int element){
    //不合法的情况
    if (index < 0 || index > list->size)
    {
        printf("输入的index非法!\n");
        return;
    }
    //插入数据
    //1.将数据封装到node结构体的变量中
    Node *node = (Node *)malloc(1 * sizeof(Node));
    node->data = element;

    //找到index的位置进行插入操作
    if (index ==0)
    {
        node->next = list->next;
        list->next = node;
        list->size++;
        return;
    }else if (index < list->size)
    {
        Node *currentnode = list->next;//指向有数据的首元素
        for (int i = 0; i < index; i++)
        {
            currentnode = currentnode->next;
        }
        
        node->next = currentnode->next;
        currentnode->next = node;

        list->size++;
        return;
    }
    
    

}
// 在末尾插入元素
void insertEnd(LinkedList *list, int element){

    insertAt(list,list->size,element);


}
// 删除指定位置的元素并返回被删除的元素
int deleteAt(LinkedList *list, size_t index){

    if (index < 0 || index >= list->size)
    {
        printf("不合法!\n");
        return;
    }

    Node * deleteNode = list->next;
    int deleteElem = deleteNode->data;

    if (index == 0)
    {
        
        list->next = deleteNode->next;


    }else{
        Node *currentNode = list->next;
        for (int i = 0; i < index -1; i++)
        {
           currentNode = currentNode->next;
        }       
        currentNode->next = deleteNode->next;

        
    }
            //获取要删除的node的数据
 
        list->size --;
        free(deleteNode);

        return deleteElem;
    
    


}
// 删除末尾元素
int deleteEnd(LinkedList *list){

    deleteAt(list,list->size-1);

}
// 获取指定位置的元素
int getElementAt(const LinkedList *list, size_t index){

    if (index < 0 || index >= list->size)
    {
        printf("输入的index不合法!\n");
        return -1;
    }

   Node *currentNode =  list->next;
   for (int i = 0; i < index; i++)
   {
    currentNode = currentNode->next;
   }

   return currentNode->next;
   

    

}
// 修改指定位置的元素
void modifyAt(LinkedList *list, size_t index, int newValue){

        if (index < 0 || index >= list->size)
    {
        printf("输入的index不合法!\n");
        return -1;
    }

   Node *currentNode =  list->next;
   for (int i = 0; i < index; i++)
   {
    currentNode = currentNode->next;
   }
     currentNode->data = newValue;



}
// 释放链表内存
void destroyLinkedList(LinkedList *list){
    Node * currentNode =  list->next;

    for (int i = 0; i < list->size; i++)
    {
        Node * tempNode = currentNode;
        currentNode = currentNode->next;
        free(tempNode);
       

    }
    list->next = NULL;
    list->size = 0;    

}



int main(){

    LinkedList list;
    initLinkedList(&list);

    insertAt(&list,0,10);
        insertAt(&list,0,20);

    insertAt(&list,0,30);

    size_t count = getLength(&list);
    printf("%d",count);

    getchar();

    return 0;
}
  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值