陈越、何钦铭《数据结构》第二讲线性结构 笔记

本文详细介绍了线性结构的概念,包括线性表、堆栈和队列的顺序存储和链式存储实现。讨论了线性表的插入、删除操作,堆栈的Push函数设计,以及如何用两个堆栈模拟队列。同时,探讨了实际生活中堆栈和队列的应用场景,并提供了课后练习,涉及多项式运算、链表反转和栈的推入序列验证。
摘要由CSDN通过智能技术生成

《数据结构》第二讲 线性结构

2.1线性表及其实现

2.1.1引子:多项式表示 

例:一元多项式及其运算
一元多项式: f(x) = a0 + a1x + a2x^2 + ……+ a(n-1) x ^ (n-1) + an x^n
主要运算:多项式相加、相减、相乘等
如何表示多项式?
多项式的关键数据:多项式项数n,各项系数ai及指数i
方法1:顺序存储结构直接表示
数组各分量对应多项式各项:a[i]:项x^i的系数ai
例如:f(x) = 4*x^5 - 3*x^2 +1 表示成a[0] = 1,a[1] = 0,a[2] = -3,a[3] = 0,a[4] = 0 ,a[5] = 4 
两个多项式相加:两个数组对应分量相加
问题:如何表示多项式x+3*x^2000?则至少需要大小为2001的数组,造成空间的巨大浪费。
方法2:顺序存储结构表示非零项
每个非零项涉及两个信息:系数ai,指数i,可以把多项式看成是一个(ai,i)二元组的集合
用结构数组表示:数组分量是由系数ai,指数i组成的结构,对应一个非零项。按指数大小有序储存

相加过程:从头开始,比较两个多项式当前对应项的指数,指数大的则输出,指数相同则对应系数相加后输出。
方法3:链表结构存储非零项
链表中每个结点存储多项式中的一个非零项,包括系数和指数两个数据域以及一个指针域。
typedef struct PolyNode* Polynomial;
struct PolyNode{
	int coef;	//系数 
	int expon;	//指数 
	Polynomial link;
}; 
其加法运算的逻辑过程和方法2相同。

2.2.1线性表及顺序存储

什么是线性表
多项式表示问题的启示:1.同一个问题可以有不同的表示(存储)方法;2.有一类共性问题:有序线性序列的组织和管理
线性表(Linear List):由同类型数据元素构成有序序列的数据结构。表中元素个数称为线性表的长度;线性表没有元素时称为空表;表起始位置称表头,表结束位置称表尾。

线性表的顺序存储实现
利用数组的连续存储空间顺序存放线性表的各元素
typedef struct LNode* List;
struct LNode{
	ElementType Data[MAXSIZE];	//存储元素的数组 
	int last;	//最后一个元素的位置 
};
struct LNode L;
List Ptrl;
访问下标为i的元素:L.Data[i]或Ptrl->Data[i]
线性表的长度:L.Last + 1或Ptrl->Last + 1
主要操作的实现
1.初始化(建立空的顺序表)
List makeEmpty()
{
	List Ptrl;
	Ptrl = (List) malloc(sizeof(struct LNode));
	Ptrl->last = -1; 
	return Ptrl;
 } 
2.查找
int find(ElementType x,List Ptrl)
{
	int i = 0;
	while(i <= Ptrl->last && Ptrl->Data[i] != x)
		i++;
	if(i > Ptrl->last)	
		return -1;	//如果没找到,返回-1 
	else
		return i;	//找到后返回的是存储位置 
}
查找成功的平均次数为(n+1)/2,平均实现性能为O(n)

2.1.3顺序存储的插入和删除

3.插入(第i(1<=i<=n+1)个位置上插入一个值为x的新元素)

void insert(ElementType x,int i,List Ptrl)
{
	int j;
	if(Ptrl->last == MAXSIZE - 1)	//表空间已满,不能插入 
	{
		printf("表满\n");
		return;	
	}	
	if(i < 1 || i > Ptrl->last + 2)	//检查插入位置的合法性
	{
		printf("位置不合法\n");
		return;
	 } 
	 for(j = Ptrl->last;j >= i - 1; j--)
		Ptrl->Data[j+1] = Ptrl->Data[j];	//将ai~an倒序向后移动 
	Ptrl->Data[j] = x;	//将新元素插入 
	Ptrl->last++;		//Last仍指向最后元素 
	return;
 }

平均移动次数为n/2,平均时间性能为O(n)

4.删除(删除表的第i(1<=i<=n)个位置上的元素)


 void delete(int i,List Ptrl)
 {
 	int j;
 	if(i < 1 || i > Ptrl->last + 1)	//检查空表及删除位置的合法性 
 	{
 		printf("不存在第%d个元素",i);
 		return;
	 }
	 for(j = i;j < Ptrl->last;j++)
		Ptrl->Data[j-1] = Ptrl->Data[j];	//将ai+1~an顺序向前移动
	Ptrl->last--;	//last仍指向最后元素 
	return;
  } 
平均移动次数(n-1)/2,平均时间性能为O(n)

2.1.4链式存储及查找

线性表的链式存储实现
不要求逻辑上相邻的两个元素物理上也相邻;通过“链”建立起数据元素之间的逻辑关系
插入、删除不需要移动数据元素,只需要修改“链”
typedef struct LNode* List;
struct LNode{
	ElementType Data;
	List Next;
}; 
struct LNode L;
List Ptrl;
主要操作的实现
1.求表长
int length(List Ptrl)
{
	List p = Ptrl;	//p指向表的第一个结点
	int j = 0;
	while(p){
		p = p->Next;
		j++;	//当前p指向的是第j个结点 
	} 
	return j; 
}
时间性能为O(n)
2.查找
(1)按序号查找:findKth
List findKth(int K,List Ptrl)
{
	List p = Ptrl;
	int i = 1;
	while(p != NULL && i < K)
	{
		p = p->Next;
		i++;
	}
	if(i == K)
		return p;	//找到第K个,返回指针 
	else
		return NULL;	//否则返回空 
 } 
(2)按值查找:find
List find(ElementType x,List Ptrl)
{
	List p = Ptrl;
	while(p != NULL && p->Data != x)
		p = p->Next;
	return p; 
}
平均时间性能O(n)

讨论2.1链式存储中findKth函数的另一种实现?

如果将链式存储中FindKth的函数实现(如下)做个修改:把函数最后的if语句判断条件改为判断p是否为NULL,即:

  1. if (p==NULL) return NULL;
  2. else return p;

或者说直接简化为:return p;

对于这样的修改,程序还正确吗?为什么?

  1. List *FindKth( int K, List *PtrL )
  2. {     List  *p = PtrL;
  3.        int  i = 1;
  4.        while (p !=NULL && i < K ){
  5.               p = p->Next;
  6.               i++;  
  7.        }
  8.        if(i == K) 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值