数据结构:顺序表与链表

        本篇博客在介绍完大致概念后有些比较适应的题大家可以去理解顺序表和链表的应用

目录

一、顺序表(如高铁连续)

        1、静态顺序表:使用定长数组存储元素(与数组类似,但利用数组构成的结构)

         2、动态顺序表:能够动态开辟数组存储

        顺序表功能的接口实现: gitee: SeqList.h/SeqList.c

二、链表 (如火车之间有结点)

        1、单向不循环无头结点链表

        链表功能的实现接口:gitee:SList.h/SList.c

        2、双向循环带头结点链表

        双向链表接口的实现:gitee:DList.h/DList.c


        在存储多数相同特性的数据元素时,一般申请一段数组,可是在数组中只能一次赋值,没有增删改查的功能。因此线性表的这种结构在一段内存上可以对内存中元素进行操作。

        常见的线性表:顺序表、链表、栈、队列等。

一、顺序表(如高铁连续)

        顺序表是在一段物理地址连续的存储单元中依次存放数据元素的线性结构,一般通过数组进行存储(顺序表是一种结构,可以对数组进行一系列操作)

        1、静态顺序表:使用定长数组存储元素(与数组类似,但利用数组构成的结构)

typedef int DataType // 统一元素类型,方便更改
// 静态顺序表结构
typedef struct SeqList 
{
	DataType array[1000];   // 存储顺序表中的元素
	int size;          // 用来记录顺序表中有多少元素
}SeqList;
// 缺陷:给定存储元素个数,不能超过上限

         2、动态顺序表:能够动态开辟数组存储

typedef int DataType // 统一元素类型,方便更改
typedef struct SeqList
{
	DataType* array;   // 在堆上申请动态的连续空间,用指针指向开辟首地址
	int capacity; // 容量:array空间中最多存储元素的个数
	int size;     // 用来记录顺序表中有效存储元素的个数
}SeqList;

         动态与静态的区别在于动态顺序表中包含容量单位,以便检查顺序表中有效元素个数是否达到容量,以此判断是否需要扩容。

        顺序表功能的接口实现: gitee: SeqList.h / SeqList.c

数据结构 DS/2022-01-25 顺序表和链表 · vipover/学习基本代码 - 码云 - 开源中国 (gitee.com) 

        其中需要注意的就是在定义顺序表时,接口传入的均为顺序表的地址指针,则对指针直接进行更改就是对顺序表内部进行操作。

        接下来是简单的顺序表类的oj题:(均有题解)

        26. 删除有序数组中的重复项 - 力扣(LeetCode)

int removeDuplicates(int* nums, int numsSize){
    //保留第一项的值,之后与其对比,若后续不相等,保留第二项值与之后相比,不相等时对数组操作
    int count = 0 ;
    for(int i = 0; i < numsSize; i++){
        if(nums[i] != nums[count])
            nums[++count]=nums[i];
    }
    return ++count;
}

 27. 移除元素 - 力扣(LeetCode)        27. 移除元素 - 力扣(LeetCode)

int removeElement(int* nums, int numsSize, int val){
    int count = 0 ;
    for(int i = 0; i < numsSize; i++){
        if(nums[i] == val)
            count++;
        else
            nums[i - count] = nums[i];
    }
    return numsSize - count;
}

        88. 合并两个有序数组 - 力扣(LeetCode)

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
    int end1 = m-1, end2 = n-1;
    int index = m+n-1;
    while(end1 >= 0 && end2 >= 0){
        if(nums2[end2] >= nums1[end1])
            nums1[index--] = nums2[end2--];
        else
            nums1[index--] = nums1[end1--];
    }
    while(end2 >= 0){
        nums1[index--] = nums2[end2--];
    }
}

总结一下:顺序表就是可在数组上进行操作的一种结构,其中题解需要找到顺序表的特性。如:26题中,需要通过建立新指针的方式指向第一个元素,当找到重复项在向后移一位并取代当前位置的值即可。27题中,将需要移除的元素跳过,将后续元素前移覆盖移除元素,利用任意位置删除的功能改变而来。


二、链表 (如火车之间有结点)

        相比与顺序表,链表是物理地址不连续的存储结构,其开辟的空间之间用指针链接,则不需要考虑顺序表中扩容以及扩容空间浪费的问题。

如上图所示,链表结构为不连续的地址(单向不循环无头结点链表)

学习链表需要了解链表的三种基本形式:是否带头结点、是否循环、是否双向指向。接下来用俩个例子介绍链表        

        1、单向不循环无头结点链表

        不带头结点的话,则开辟链表时,定义用的指针直接操作链表,即定义的指针指向就是链表结构的第一个结点,因此对链表进行更改时,需要传递开辟链表的指针的地址(即二级指针操作),用二级指针在接口中操作原链表的结构,这是不带头结点操作链表的重点!!!

        单向链表的结构:

typedef int DataType;

typedef struct SListNode {
	struct SListNode* next;//链表的下一个节点
	DataType data;
}Node;


Node* pList = NULL;//创建的不带头结点的链表起始地址

切记:

1、单向链表无法回溯之前的地址,只能进行单向操作,因此对头操作的增删方法是最优选

2、因为不需要考虑扩容问题,则增添时只需要增加新结点即可

        链表功能的实现接口:gitee:SList.h / SList.c

数据结构 DS/2022-01-25 顺序表和链表 · vipover/学习基本代码 - 码云 - 开源中国 (gitee.com)

        2、双向循环带头结点链表

        一般链表均是带头结点的,头结点的作用就好比在顺序表中直接创建一个结构,再传入结构地址进行链表操作,不同之处是链表中的头结点只起一个传递地址的作用,不在头结点中进行功能操作;而顺序表需要在创建的结构中进行功能操作。

        循环的意义就是在结点之间增加可回溯前结点地址的功能,不再是单向操作

        双向链表结构:

typedef int DataType;

typedef struct DListNode
{
	struct DListNode* next;
	struct DListNode* prev;
	DataType data;

}DListNode;


DListNode* DList = NULL;//这里的指针指向头节点,而非链表的第一个节点

双向循环链表中,头结点的前一个结点就是链表的最后一个结点,头结点的下一个结点是链表的第一个结点,因此头结点只传递地址。

        双向链表接口的实现:gitee:DList.h / DList.c

数据结构 DS/2022-01-25 顺序表和链表 · vipover/学习基本代码 - 码云 - 开源中国 (gitee.com)


        链表的基本功能和结构了解后,看一些用链表结构解决的oj题:

        203. 移除链表元素 - 力扣(LeetCode)

        需要考虑删除元素是否为第一个结点即可

        206. 反转链表 - 力扣(LeetCode)

        这题的意义在于介绍单向链表中,需要想办法找到结点之前的位置和之后的位置

        876. 链表的中间结点 - 力扣(LeetCode)

        链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com) 

        这俩道题在链表中,介绍了经典的快慢指针算法问题,利用快慢指针解决中间值或者等距离移动等应用

        链表的回文结构_牛客题霸_牛客网 (nowcoder.com)

        这道题应用单链表中的快慢指针、单链表的前位置回溯、后位置记忆等,是一道较为综合的题

        160. 相交链表 - 力扣(LeetCode)

        这个是比较考察单链表的定义,一个结点有且只有一个指向下一个位置


        顺序表和链表的大概应用就结束了,当然最重要的是在接口实现中理解代码的应用,希望可以帮助大家吧,代码中我也标有很多注释,愿大家一起进步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值