《数据结构与算法》| 清华大学 | 第二章 | 顺序表和链表

抽象数据类型

抽象数据类型(ADT, Abstract Data Type):数据模型 + 相关操作。
数据机构(DS, Data Structure):实现ADT的一套算法。

抽象数据类型内部使用数据结构 实现(implementation),封装为统一的 接口(interface) 函数,提供外部用户接口手册以 应用(application) 于实际问题。

在这里插入图片描述
接口操作可分为 静态操作动态操作:静态操作仅读取,数据结构内容和组成一般不变,如[]find();动态操作需写入,数据结构的局部或整体将改变,insert()remove()

数据存储和组织方式也分为 静态存储动态存储:静态存储的向量,整体创建与销毁数据空间,逻辑和物理存储均连续,支持高效静态操作;动态存储的列表,动态地为数据元素分配和回收物理空间,逻辑连续、物理可不连续,支持高效动态操作。

顺序表

顺序表:使用一组地址连续的存储单元依次存储线性表的数据元素。顺序表 A [ n ] A[n] A[n] = { a 0 , a 1 , . . . a i . . . a n − 1 a_0, a_1,...a_i...a_{n-1} a0,a1,...ai...an1},其中 a i − 1 a_{i-1} ai1 a i a_i ai 的前驱元素, a 0 a_0 a0 ~ a i − 1 a_{i-1} ai1 构成 a i a_i ai 前缀。
在这里插入图片描述

接口

// Array.h	
#define ElemType int	
#define MaxSize	50	
typedef struct {
	ElemType data[MaxSize];		// 顺序表的元素 
	int length;					// 顺序表的当前长度 
}SqList;						// 顺序表的类型定义 

// 静态操作
int LocateElem(SqList L, ElemType e);

// 动态操作
bool Insert(SqList &L, int i, ElemType e);
bool Delete(SqList &L, int i, ElemType &e); 

实现

1. 空间管理

顺序表是开辟数组 data[ ] 并使用一段地址连续的物理空间存储元素,其中 MaxSize 表示总容量, length 表示当前实际容量。

#define MaxSize	50	
typedef struct {
	ElemType data[MaxSize];		// 顺序表的元素 
	int length;					// 顺序表的当前长度 
}SqList;						// 顺序表的类型定义 

顺序表的容量 Maxsize 固定,容易出现上溢、下溢等问题,同时实际开发时难以预测空间的需求量。

3. 静态操作

  • 按秩查找
L.data[i];
  • 按值查找

在这里插入图片描述

int LocateElem(SqList L, ElemType e) 
{
	for (int i=L.length-1; i>=0; i--)
		if (L.data[i]==e)
			return i+1;			// 下标为 i 的元素值等于e, 返回其位序 i+1 
	return 0;					 
}

4. 动态操作

  • 插入

在这里插入图片描述

bool Insert(SqList &L, int i, ElemType e) 
{
	if (i<1||i>L.length+1)		// 判断 i 的范围是否有效 
		return false; 
	if (L.length>=MaxSize)		// 当前存储空间已满,不能插入
		return false;
		
	for (int j = L.length; j>=i; j--) // 自后向前,后继元素顺次后移一个单元
		L.data[j] = L.data[j-1];
	L.data[i-1] = e;	L.length++;
	return true;
} 
  • 删除

在这里插入图片描述

bool Delete(SqList &L, int i, ElemType &e) 
{
 	if (i<1||i>L.length)		// 判断 i 的范围是否有效 
	 	return false; 
	
	e = L.data[i-1];
	for (int j=i; j<L.length; j++)	// 自前向后,后继元素顺次前移一个单元
		L.data[j-1] = L.data[j]; 
	L.length--;
	return true;
}	

链表

在这里插入图片描述
链表:采用动态存储策略,元素称为节点,各节点通过指引或引用连接,逻辑构成线性序列。相邻节点互称前驱和后继,前驱和后继存在则唯一,无前驱节点称为首节点,无后继节点称为末节点。

接口

// ListNode.h
#define ElemType int	

struct LNode;					
typedef struct LNode* LinkList; // 链表
typedef struct LNode* Position; // 链表结点

typedef struct LNode{			// 定义单链表结点类型 
	ElemType data;				// 数据域 
	Position next;				// 指针域 
};				 

void Insert(LinkList L, int i, ElemType e);
void Delete(LinkList L, int i, ElemType &e);
Position Get(LinkList L, int i); 
Position Find(LinkList L, ElemType e);

实现

1. 空间管理

链表结点 LNode 包含数据域 data 和指针域 next,其中 data 表示数据元素, next 表示后继节点的地址。

struct LNode;					
typedef struct LNode* LinkList; // 链表
typedef struct LNode* Position; // 链表结点

typedef struct LNode{			// 定义单链表结点类型 
	ElemType data;				// 数据域 
	Position next;				// 指针域 
};		

2. 静态操作

  • 按秩查找
Position GetElem(LinkList L, int i)
{
	int j=1; 
	Position p=L->next;
	
	if (i==0)	return L;		// 若i等于0, 返回头结点 
	if (i<1)	return NULL;	// 若i无效,返回NULL 
	
	while (p!=NULL && j<i) {	// 查找第i个结点 
		p=p->next;	j++;
	}
	return p;
}
  • 按值查找
Position LocateElem(LinkList L, ElemType e)
{
	Position p=L->next;
	while (p!=NULL && p->data!=e)	// 查找值为e的结点 
		p=p->next;
	return p;
}

3. 动态操作

  • 插入
void Insert(LinkList L, int i, ElemType e);
{
	Position p=GetElem(L,i-1);	// 插入位置前驱结点
	Position s=malloc(sizeof( struct Node ));
	
	if (s==NULL) {
		printf("Out of Space!!!");
		return 0;
	}
		
	s->data=e;	
	s->next=p->next;
	p->next=s;
}
  • 删除
void Delete(LinkList L, int i, ElemType &e);
{
 	Position p=GetElem(L,i-1);	// 删除位置前驱结点 
	Position q=NULL;
	
	q=p->next;	e=q->data;
	p->next=q->next;
	free(q);
}	
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值