数据结构-1-线性表

数据结构-1-线性表

  • 线性表的抽象数据类型定义
  • 线性表的顺序储存结构
  • 线性表的链式存储结构
    • 单链表
    • 循环链表
    • 双向链表
    • 静态链表

线性表的抽象数据类型定义

ADT 线性表(List)
Data
	线性表的数据对象集合为{a1, a2, …,an },每个元素类型均为DataType。其中,除第一个
	元素a1外,每一个元素有且只有一个直接前驱元素,除最后一个元素an外,每一个元素有且
	只有一个直接后继元素。数据元素之间的关系是一对一的关系。
Operation
	InitList( *L) :		初始化操作,建立一个空的线性表L
	ListEmpty(L):			若线性表为空,返回ture
	ClearList(*L):			将线性表清空
	GetElem(L, i, *e):	将线性表L中的第i个位置元素值返回给e
	LocateElem(L, e):		在线性表L中查找与给定值e相等的元素,
							如果成功,返回该元素在表中序号;否则返回0
	ListInsert(*L, i, e):	在线性表L中的第i个位置插入新元素e
	ListDelete(*L, i, *e):删除线性表L中第i个位置元素,并用e返回其值
	ListLength(L):  		返回线性表L的元素个数
endADT

线性表的顺序储存结构

//顺序存储结构
#define MAXSIZE 20   //存储空间初始分配量
typedef int ElemType;	//ElemType类型根据实际情况而定,这里假设为int
typedef struct
{
	ElemType data [MAXSIZE];	//数组存储数据元素,MAXSIZE为数组长度
	int length;									//length为线性表长度
}SqList;

插入操作 ListInsert( *L, i, e)

  • 如果位置不合理,抛出异常;
  • 如果线性表长度大于等于数组长度,抛出异常或动态增加容量;
  • 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置;
  • 将要插入元素填入位置i处;
  • 表长加1。

删除操作 ListDelete(*L, i, *e)

  • 如果位置不合理,抛出异常;
  • 取出删除元素;
  • 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;
  • 表长减1。

线性表的链式存储结构

单链表

若有头结点,则头指针指向头结点,头结点不存储数据,头结点的指针指向第一个结点;若无,则头指针指向第一个结点。其他均存储本身的信息和下一个结点的地址,最后一个结点存储的地址为NULL。

//线性表的单链表存储结构
typedef struct Node
{
	ElemType data;
	struct Node *next;
} Node;
typedef struct Node *LinkList;

获取链表第i个数据:

  1. 声明一个p指向第一个结点,初始化j从1开始;
  2. 当j
  3. 若到链表末尾p为空,则说明第i个结点不存在;
  4. 否则返回结点p的数据。

单链表的插入:

  1. 声明一个p指向第一个结点,初始化j从1开始;
  2. 当j
  3. 若到链表末尾p为空,则说明第i个结点不存在;
  4. 否则,生成一个空结点s; //s = (LinkList) malloc (sizeof(Node));
  5. 将数据元素e赋值给s->data;
  6. 单链表的插入标准语句s->next=p->next; p->next=s;
  7. 返回成功。

单链表的删除:

  1. 声明一个p指向第一个结点,初始化j从1开始;
  2. 当j
  3. 若到链表末尾p为空,则说明第i个结点不存在;
  4. 否则,将欲删除的结点p->next赋值给q;
  5. 单链表的删除标准语句p->next=q->next;
  6. 将q结点中的数据赋值给e,作为返回;
  7. 释放q结点;
  8. 返回成功。

循环链表

将单链表中终端结点的指针由指向NULL改为指向头结点。
为方便,指向头结点的头指针可废除,新增尾指针(rear)指向最后一个结点,此时,第一个结点便可用rear->next->next表示。

双向链表

//双向链表存储结构
typedef struct DulNode
{
	ElemType data;
	struct DulNode *prior;	//前驱
	struct DulNode *next;	//后继
} DulNode, *DuLinkList;

双链表的插入: (顺序不可乱,先从s的前后指向,再p->next的前驱,p的后继)

s->prior = p;			//s的前驱指向p
s->next = p->next;		//s的后继指向p->nex
p->next->prior = s;		//p->next的前驱指向s
p->next = s;			//p的后继指向s

双链表的删除:

  1. p->prior的后继指向p->next;
  2. p->next的前驱指向p->prior;
  3. 释放p。

静态链表

即不用指针的链表。

//线性表的静态链表存储结构
#define MAXSIZE 1000
typedef struct
{
	ElemType data;
	int cur;
} Component, StaticLinkList [MAXSIZE];

未被使用的数组元素称为备用链表。
第一个和最后一个元素不存数据,第一个元素(下标为0)的cur存放备用链表的第一个结点的下标,而最后一个元素的cur存放第一个有数值的结点的下标。

静态链表的插入:

  1. 取得备用链表的第一个结点的下标,即下标为0的结点的cur;
  2. 将备用链表的第一个结点的cur赋值给下标为0的结点的cur,即使头结点指向原备用链表的第二个结点的下标;
  3. 循环找到第i-1个已赋值的结点,将其cur(即第i个已赋值结点的下标)赋值给备用链表第一个结点的cur,并将备用链表第一个结点的下标赋值给第i-1个已赋值结点的cur;
  4. 将数据赋值给原备用链表第一个结点。

静态链表的删除:

void Free_SSL (StaticLinkLIst space, int k)
{
	space [k].cur = space [0].cur;
	space [0].cur = k;
}

status ListDelete (StaticLinkList L, int i)
{
	int j,k;
	if(i<1||i>ListLength(L))
		return ERROR;
	k = MAX_SIZE-1;				//最后一个结点存储着第一个已赋值结点的下标
	for(j=1;j<=i-1;j++)			
		k = L[k].cur;			//找到第i-1个已赋值的结点,注意j与k
	j = L[k].cur;				//将第i个已赋值的结点的下标赋值给j
	L[k].cur = L[j].cur;		//使第i-1的结点指向第i+1
	Free_SSL(L,j);				//被删除的结点的cur指向头结点的cur,
								//原备用头结点指向原第i个已赋值的结点
	return OK;
}

你可能感兴趣的:(数据结构)