首页 > 其他分享 >数据结构2——线性表的链式存储

数据结构2——线性表的链式存储

时间:2025-01-21 16:29:12浏览次数:3  
标签:结点 NULL 线性表 指向 LNode next 链式 数据结构 指针

前言

顺序存储结构的缺点:① 插入、删除操作需要移动大量的元素。 ②  预先分配空间需按最大空间分配,利用不充分。 ③ 表容量扩充十分不方便(可能会产生效率问题)。

链式存储结构恰好弥补了顺序存储这些缺陷。

1.认识线性表链式存储

1.1线性表链式存储的构成

① 可用一组任意地址的存储单元存储线性表的数据元素。② 每个数据元素,除存储本身信息外,还需存储其直接(相邻)关系元素的存储地址 (指针)。 ③ 利用指针实现了逻辑上相邻的元素可以用不相邻的存储单元存放(顺序存储就是相邻存储单元)。④ 利用指针对指向的元素进行访问与操作。

数据域:元素本身信息。指针域(1个或多个):指向具有直接关系元素的指针。 

链式存储结构可看作由一个(或多个)定位指针 + 数个结点构成的一种数据结构。下图以单链表为例

每个结点中只含一个指针域的链表叫单链表。 单链表中每个结点的的指针域存放其直接后继结点的指针(存储地址)。 开始结点无前趋,故应设头指针head指向开始结点。 同时,由于终端结点无后继,故终端结点的指针域为空, 即null(图示中用^表示)。 

1.2头结点

在第一个结点之前虚加一个 “头结点”,以指向头结点的指针为链表的头指针。其不表示真正元素的数据,只用于存放第一个结点的地址。 头结点指针域为空表示线性表为空。头结点类似于火车头,由头指针指向头结点,这样每次数据访问便从头结点开始访问,使得访问“有迹可循”。

1.3链式存储结构优缺点

优点: ① 任何操作都不需要移动结点,只要修改指针即可。适合做插入或删除操作。②不需预先分配空间。

缺点: ①不能随机存取,查找速度慢。 ② 指针占用额外存储空间。


2.线性表链式存储操作原理

基本操作:

(1)初始化InitList(&L)---创建一个新的空表

(2)销毁DestroyList(&L)---存在->不存在

(3)置空表ClearList(&L)---线性表->空集

(4)求长度ListLength(L)

(5)取元素GetElem(L ,position)---按序号查找

(6)定位函数LocateElem(L, x)---找出第一个与x相同值的位置

(7)插入ListInsert(&L, position, x)

(8)删除ListDelete(&L, position)

2.1初始化

#include<stdio.h>
using namespace std;
struct LNode{
int data;      //数据域
LNode *next;   //指针域
};
int main()
{
    LNode *L;    //创建头指针
    L=new LNode; //将头指针指向新开的LNode地址,即头指针指向头结点
    L->next=NULL;//将头结点的next指向NULL,至此完成头指针和头结点创建
}

2.2求长度

求表长:从第一个元素开始逐个计数,直到最后一个指针域为空时,计数结束。

在链表中,头指针应始终指向头结点以保持链表访问稳定。因此在对链表进行操作时,应新建一个指针p,指向头指针指向的头结点,通过指针p来对链表访问与操作。我们用 “ p=p->next ” 进行遍历操作:将p指向头结点,进行条件判断(p->next是否为空)是否执行遍历操作。

LNode *p=L;
while(p->next!=NULL)
{
    p=p->next;
}

2.3取元素和找元素位置

运用p=p->next语句可完成查询,但需注意的是:不论位置position值“ i ”为多少,都必须从第1个结点开始起“点数”, 直数到第 i 个为止。

当 i 大于表长时,p后移若干个结点后就可能指空。这时,应该停止p的遍历过程。因此在循环中需要判断是否已经遍历到表尾。那么有两种情况导致循环的退出:1、找到第i个结点;2、i不在有效范围内。做链表的操作最好能自主画图深入理解。

2.4插入元素

如何创建新结点存储信息?

LNode *temp = new LNode;
temp->data = WhatYouGet;
temp->next = NULL;

如何插入这个新结点在所选位置?①指针p指向位置前一个的结点,②新结点的next指针域指向p的next指针域 指向 的地址,③最后更新p的next指针域,使其指向新结点。

LNode *p = The_Front_Point;
指针p指向前一个结点
temp->next = p->next;
新结点的next指针域 指向 p的next指针域指向的地址
p->next = temp;
更新p的next指针域,使其指向新结点

2.5删除元素

①指针p指向删除结点前一个的结点,创建一个新结点用于指向删除结点,②新结点指向p的next指针域 指向 的地址,③最后更新p的next指针域,使其指向新结点next指向的地址。最后delete新结点

LNode *p = The_Del_Front_Point;
LNode *del;

del = p->next;
p->next = del->next;

delete del;

3.线性表链式存储操作实现

ps:算法代码以头指针、头结点、单链表为例

typedef int ElemType;
struct LNode{
ElemType data;
LNode *next;
};
typedef LNode* LinkList;
//1. 初始化链表
bool InitList( LinkList &L )
{
	if( L!=NULL)
		return false;
	L = new LNode;     //生成头结点
	L->next = NULL;    //头结点next指向NULL
	return true;
}
//2. 销毁表
bool DestroyList( LinkList &L )
{
    if(L->next!=NULL)
    {
        cout<<"请先执行清空表操作";
        return false;
    }
	delete L;
	return true;
}
//3. 清空表
bool ClearList( LinkList &L )
{
	LNode *p=L->next;
	LNode *del;
	while(p)
	{
		del=p;
		p=p->next;
		delete del;
	}
	return true;
}
//4. 求表长
int ListLength_L( const LinkList &L )
{
	LNode *p=L;
	int count=0;
	for(p=L; p->next!=NULL; p=p->next)
	{
		++count;
	}
	return count;
}
//5. 取表中第i个元素
bool GetElem_L( const LinkList &L , int i , ElemType &e )
{
	if(i<=0)
		return false;
	LNode* p=L;
	while(i!=0 || p)
	{
		--i;
		p=p->next;
	}
	if(i>0)
	{
        cout<<"输入位置大于表长";
		return false;
	}
	e=p->data;
	return true;
}

//6. 定位函数,找出表中第一个与e相等的元素,并返回这个结点,如果没有找到,可返回NULL
LNode* LocateElem( const LinkList &L , ElemType e )
{
	LNode *p=L->next;
	while(p->data!=e)
	{
		p=p->next;
	}
	if(p)
		return p;
	return NULL;//实现时根据需要修改返回值,如果不存在该结点,返回NULL,否则返回结点指针
}

//7. 在第i个位置插入元素e
bool ListInsert( LinkList &L , int i , ElemType e )
{
	LNode *p;
	p=L;
	int j=0;
	while(p && j<i-1)
	{
		p=p->next;
	}
	if(!p || j>i-1)	return false;
	LNode *n=new LNode;
	n->data=e;
	n->next=p->next;
	p->next=n;
	return true;
}
//7.1 头插法
bool ListInsert_Head( LinkList &L , ElemType e)
{
    LNode *p=L;
    LNode *n=new LNode;
	n->data=e;
	n->next=p->next;
	p->next=n;
    return true;
}
//8. 删除表中第i个元素,并在主程序用“ElemType e”接收该元素的值
bool ListDelete( LinkList &L , int i , ElemType &e )
{
	if(i<=0)
    {
        cout<<"请输入正确的位置(大于或等于1)";
		return false;
    }
	LNode* p=L;
	LNode* del;
	--i;
	while(i!=0 && p)
	{
		p=p->next;
		--i;
	}
	if(i>0)
    {
        cout<<"输入位置大于表长";
		return false;
    }
	del=p->next;
	e=del->data;
	p->next=del->next;
	delete del;
	return true;
}

标签:结点,NULL,线性表,指向,LNode,next,链式,数据结构,指针
From: https://blog.csdn.net/QiQi_sviper/article/details/145277516

相关文章

  • 【轻松掌握数据结构与算法】动态规划
    引言在本章中,我们将尝试解决那些使用其他技术(例如分治法和贪心法)未能得到最优解的问题。动态规划(DP)是一种简单的技术,但掌握起来可能比较困难。识别和解决DP问题的一个简单方法就是尽可能多地解决各种问题。“编程”一词与编码无关,而是源自文献,意思是填充表格,类似于线性规划。......
  • 顺序存储和链式存储
    数据结构数据结构是计算机存储、组织数据的方式数据结构是指互相之间存在一种或多种特定关系的数据元素的集合比如自定义的一个类也可以称为一种数据结构,类是一个自己定义的数据组合规则数据结构简单来说就是人定义的存储数据和表示数据之间关系的规则常用的数据结构数组、......
  • 单调队列:实用而好写的数据结构
    前言|Preface这几天连续做了好几道单调队列的题,难度从绿到蓝不等,摸索出了一些经验,也总结了一些单调队列的特点和规律。概述|Outline顾名思义,单调队列的重点分为「单调」和「队列」。「单调」指的是元素的「规律」——递增(或递减)。「队列」指的是元素只能从队头和队尾进......
  • 数据结构与算法之递归: LeetCode 39. 组合总和 (Ts版)
    组合总和https://leetcode.cn/problems/combination-sum/description/描述给你一个无重复元素的整数数组candidates和一个目标整数target,找出candidates中可以使数字和为目标数target的所有不同组合,并以列表形式返回。你可以按任意顺序返回这些组合candid......
  • 01 序论(数据结构实战)
    计算机的发展与用途:早期的计算机:最初,计算机主要是用来进行数学运算,像是加减乘除这种“数值计算”。它们主要用在科学研究、工程计算等需要大量数字计算的领域。现在的计算机:现代的计算机用途广泛,已经不仅仅局限于处理数字。它们还处理许多其他类型的数据,比如文字、表格、图片......
  • 数据结构-堆及堆排序
    1.堆的定义堆(Heap)是一种数据结构,通常是一个完全二叉树。在堆中,每个节点都有一个与其相关的值,并且满足堆的性质。堆分为两种类型:大堆和小堆。大堆:在大堆中,对于每个非叶子节点,其值都大于或等于它的子节点的值。也就是说,根节点的值是整个堆中的最大值。小堆:与大堆相反,在小堆中,对......
  • 【第一天】零基础入门刷题Python-算法篇-数据结构与算法的介绍(持续更新)
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、Python数据结构与算法的详细介绍1.基本概念2.Python中的数据结构1.列表(List)2.元组(Tuple)3.字典(Dictionary)4.集合(Set)5.字符串(String)3.Python中的常用算法1.排序算法2.搜索算法3.递......
  • 数据结构——栈
    1、栈的概念(1)是一种特殊的线性表,只能在一端进行插入或删除操作(2)逻辑结构:线性结构;存储结构:既可以是顺序存储,也可以是链式存储(3)栈顶:允许插入或删除的一端(4)栈底:不允许插入或删除的一端,位置固定不变(5)空栈:栈中没有元素(6)使用特点:LIFO(后进先出)2、操作#define_CRT_SECURE_NO_......
  • C语言实现顺序存储线性表
    ////Createdbystevexiaohuzhaoon2025/1/20.///****线性表的顺序存储结构实现*特点:逻辑上相邻的元素,物理上也相邻**/#include<stdio.h>#include<stdlib.h>#defineMAXSIZE100//定义线性表的最大长度//1.定义图书结构体Booktypedefstr......
  • 2024网安数据结构恐龙提纲
    2024网安数据结构......