数据结构2-线性表

线性表概念

定义:具有相同特性数据元素的一个有限序列。

元素个数叫作线性表长度,用n(n≥0)表示,当n为0时,表示线性表是一个空表


1.逻辑特性:线性结构

线性结构的定义:数据元素之间存在一对一的线性关系。

①有第一个元素(表头),有最后一个元素(表尾)空表时,第一个/最后一个元素都为空

②除第一个元素外,其他元素都有唯一的前驱
除最后一个元素外,其他元素都有唯一的后继


2.存储结构:顺序/链表

线性表的顺序存储结构是一种随机存取 (当然也可以顺序存取)的存储结构
线性表的链式存储结构是一种顺序存取 的存储结构。

1.顺序表(顺序存储):

(1)定义:把线性表中所有元素按照其逻辑顺序,依次存储到指定存储位置开始的一块连续存储空间

(2)特性:
①随机访问

②占用连续的存储空间,存储空间一次性分配

③插入操作要移动多个元素(插在表中第i个元素之后⇒移动元素个数为n-i)

④存储密度=1


2.链表(链式存储):

(1)定义:结点间的逻辑关系借助指示元素存储地址的指针(附加的指针字段)表示。
如单链表的前驱结点包含后继结点的地址信息

(2)特性:
①不占用连续的存储空间,存储空间多次分配

②不支持随机访问,只能顺序存取(要读取某个元素必须遍历其之前的所有元素才能找到并读取)

②由于需要留空间给指针域,
存储空间利用率较低,存储密度<1

③支持存储空间的动态分配(现用现划分)

④插入操作,无须移动元素


3.头指针head:

①独立的一个指针变量,不是单链表结点的指针域 指针

③头结点不是链表必需的,
但链表(非循环链表) 一定有头指针,

顺序表也可以用头指针来指示第一个元素的位置

循环链表可以仅由头指针/尾指针来表示(头指针不是必需)

③头指针具有标识链表的作用,整个链表的存取必须是从头指针开始进行,头指针冠以链表的名字(指针变量的名字)

④head->next ⇔(*head).next
(头指针指向结点 的指针域成员,也就是head指向下个结点⇒head->next指向下下个结点)

⑤若链表有头结点,则无论链表是否为空,头指针均不为空。头指针是链表的必要元素。(初声明,没有头结点时 为野指针)

顺序表头指针为空则顺序表为空


4.链表的五种形式

链表都可区分带头结点和不带头结点,运用相同,以单链表为例


1.单链表

每个结点除了数据域,还包含用以指向后继结点的指针域next。表尾(终端)结点的指针域为NULL

(1)带头结点的单链表

在带头结点的单链表中,第一个结点带有歧义
用首元结点来表示第一个元素结点
第一个结点表示线性表的第一个结点(头结点/首元结点)

①头结点(可以存储链表长度)。值域中无信息 / 指针域指向首元结点

②头指针head 存放头结点的存储位置(始终指向头结点),头指针始终不为空(声明头指针时虽然还没有头结点,但是其是一个不为空的野指针)
对指针来说,存放谁的位置,就指向谁

③从头结点的后继结点 首元结点开始存储数据

④head->next=NULL,链表为空


(2)不带头结点的单链表

第一个(元素)结点为开始结点

head直接指向开始结点,head为NULL时,链表为空


2.双链表

在单链表结点上增添了一个指针域prior,指向当前结点的前驱

仍可区分带头结点和不带头结点,且与单链表相同

(普通)双链表只是加了个前驱指针域,什么循环都没有
判断表空与普通单链表相同

3.循环单链表

将单链表的最后一个指针域(表尾结点的指针域)指向第一个结点。

此处第一个结点指的是 头结点 / 首元结点
因为循环单链表仍可区分带头结点和不带头结点

(2)判断表空
不带头结点 :
head=NULL

带头结点 :
head=head->next
带头结点的循环(单/双)链表没有空指针

4.循环双链表

(1)定义:
将双链表终端结点(表尾结点)的next指针指向链表中的第一个结点
将链表第一个结点prior指针指向终端结点

可区分带头结点和不带头结点


(2)判断表空
不带头结点 :
head=NULL

带头结点 :
head->next ==head 和 head->prior=head
任意判断一个即可
带头结点的循环双链表没有空指针

循环双链表中任一结点的前驱指针均不为空

5.静态链表

借助于一维数组,需要连续空间的链表

每个结点的指针分量指向后继结点在数组中的位置

“指针分量”:整形变量,指向下个结点在数组中的相对位置

数组第一个位置空闲(类似于头结点),指向第一个元素结点
S[0].cur即为第一个结点位置



5.链表 结点与指针的联系与区分

1.关系:当我们定义一个指针A指向一个结点时,由于结点没有名字,所以我们常用指针的名称A来作为结点的名称

A的含义:①一个结点②指向该结点的指针

2.区分:
①A指向谁⇒A此处指代指针
②free()释放A⇒A此处指代结点
因为指针变量自身所需的存储空间是系统分配的,不需要用户释放。而用户自己分配的存储空间(malloc内存空间/结点)需要自己释放



线性表结构体定义和基本操作

一.结构体定义

1.顺序表

(1)typedef struct{}Sqlist;
定义一个顺序表(结构体)类型并换名为Sqlist

(2)成员为一个元素数组(通过数组指针elem指向元素数组基地址) int *elem;
一个数组长度length和空间分配大小listsize

1-2初始化空线性表

Status Initial(SqList &L)//初始化一个空数组 引用
{
L.elem=(int )malloc(listsizesizeof(int))
//L.elem 数组 赋值 指向分配内存的指针

if(!L.elem) exit(overflow);//存储分配失败 (L.elem为NULL,则退出进程并返回OVERFLOW)

L.length=0;
L.listsize=listsize;
return ok;
}


2.单链表

(1)typedef struct LNode{}LNode,*LinkList;
定义一个单链表结点(结构体)类型并换名为LNode,

并换名struct LNode *(结点指针)类型为LinkList

结合int *(整形指针)类型理解

把int*理解成一个类型

Linklist L;定义一个结点指针类型 变量L

L为(指向)结点类型的指针变量,
标识整个顺序表


(2)
结点包括数据域(成员)int data

和指针域(成员)struct LNode *next
用本身结构体定义,所以结构体本身名不可省
next指针指向下一个结点

3.双链表

(1)typedef struct DLNode{}DLNode,* DuLinkList;
DLNode为双链表结点类型,
DuLinkList为双链表结点指针类型

(2)一个数据域 int data;
两个指针域
struct DLNode *prior;指向前驱结点的指针
struct DLNode *next;指向后继结点的指针



二.顺序表的操作

1.按元素值的查找算法

在顺序表中查找第i个值与r满足compare()的元素的次序

int LocateElem(SqList L,Elemtype e,Status(* compare)(Elemtype,Elemtype)){~}

(1)传值调用 SqList L
不改变顺序表在内存里的值

(2)函数指针

Status (* compare)(int,int)
函数指针compare指向 返回(类型)为Status,参数(类型)为int,int的函数

赋值(调用时赋值):LocateElem(L,e,comp)
comp是自己定义的一个函数,被compare指针指向,并可以由compare调用

调用:compare(a,b)/(* compare)(a,b)


(3)元素数组第一个值存放在elem[0] / *elem中, (数组首地址elem==&elem[0])

用*elem 访问数组元素⇒ 元素位序(1-n)

//i为元素次序的值,赋初值为1
int i = 1;

//给p赋顺序表的基址,通过p++来遍历顺序表
ElemType* p = L.elem;

while (i <= L.length && !(*compare)(*p++, e)) ++i;
if (i <= L.length) return i;
else return 0;
}


3.插入元素

Status Insert(SqList &L,int i,int e)//在第i个位置之前插入e
{
if(i<1||i>L.length+1) return ERROR;
//可以在第(1~n+1)个位置之前插入

if(L.length>=L.listsize)
{
Elemtype *newbase;
newbase=(int *)realloc(L.elem,(L.listsize+increament)*sizeof(Elemtype));
if(!newbase) exit(OVERFLOW);
//加一个判断,防止分配失败,原数组还被清空了

L.elem=newbase;
L.listsize+=increament;

}

int *p;
p=&L.elem[i-1];
//插入元素位置 (地址变量赋值)
for(int *q=&L.elem[L.length-1];q>=p;q–)
//q为表尾元素位置
*(q+1)=*q;

    *p=e;
L.length++;

return ok;
}

发布了46 篇原创文章 · 获赞 15 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_41850194/article/details/97374861