拔丝芋头的数据结构复习日记---Day1---线性表

< 今日知识点 >

线性表

  • 顺序存储
  • 链式存储

·
·
·

—01 多项式的表示

  • 方法1:用顺序储存结构直接表示,数组的下标表示相应的指数

但是在一些情况下会造成很大的空间浪费,如x3+x2000 ,显然这个多项式用方法1来表示要用到2001个数组空间,造成不必要的浪费

  • 方法2:顺序储存结构表示非零项,即用结构数组中的两个分量来表示,空间大大节省了,同时也可以做到运算方便(关键是要按指数递降的方式储存)在这里插入图片描述
  • 相加过程: 从头开始比较两个多项式当前对应项的指数,指数高的一项进入新的结构数组中,如果指数相等,则对应系数相加。
  • 方法3:链表结构储存非零项:链表中每个节点储存多项式中的一个非零项,包括系数和指数两个数据域以及一个指针域
    在这里插入图片描述

**相加过程:**与前面两个方法的思想是一样的。

·
·
·

—02 线性表

1、定义:线性表(Linear List)是由同类型的数据元素构成的有序序列的线性结构。

  • 在这里插入图片描述
    在这里插入图片描述
    2、顺序表的顺序存储实现:利用数组的 连续储存空间存放 线性表各个元素。
    代码:
typedef struct LNode *List;
struct LNode{
	ElementType Data[MAXSIZE];
	int Last;            //线性表的表尾
} ;

定义:List L; 或 struct LNode PtrL;

  • 访问下标为i的元素:L.Data[i] 或者 PtrL->Data[ i ];
  • 线性表的长度:L.Last+1 或者 PtrL -> Last +1

3、顺序表顺序存储的主要操作的实现

  • 初始化(建立空的顺序表)
List MakeEmpty()
{
	List L;
	L = (List) malloc (sizeof(struct LNode));
	L->Last = -1;
	return L;
}
  • 查找
int Find(ElementType X,List L) 
{
	int i = 0;
	while( L->Data[i] != X && i <= L->Last){
		i++;
		if(i > L->Last)
			return -1;
		else return i;          //如果没找到就返回-1,找到了就返回储存的位置;
	}
}
  • 插入(在第i个(1<=i<=n+1) 位置上插入一个值为X的新元素)
void Insert(ElementType X,int i,List L)
{
	int j;         //首先判断表满不满 
	if(L->Last == MAXSIZE-1) {   //表已经满了,无法插入
		printf("表满了”);
		return ;
		
	if( i<1 || i>L->Last+2 ){
		printf("位置不合法”);
		return ;
	}
	
	for( j=L->Last ; j >= i-1 ; j-- )
		L->Data[j+1] = L->Data[j] ;    //将第i到第j个元素倒序向后移动
	L->Data[i-1] = X;
	L->Last++;     //Last仍指向最后一个元素
	return ;

  • 由于数组空间是连续存放的,所以插入操作的第一步是从第i个元素开始往后挪。(将第i到第j个元素倒序向后移动)第二步才是插入。
  • 插入操作的平均移动次数为 n/2 ,平均时间性能为O(n) .

在这里插入图片描述

  • 删除(删除表中的第i个(1<=i<=n)位置上的元素
void Delete(int i,List L)
{
	int j;
	if(i<1 || i>L->Last+1){    //+1 是因为数组下标从0开始
		printf("不存在第%d个元素,i);
		return ;
	}

	for( j=i;j<=L->Last;j++)
		L->Data[j-1] = L->Data[j];
	L->Last--;
	return ;
  • 删除第i个元素,相当于第i个位置空出来了,所以要按照从左往右的顺序往前挪动元素
  • 删除操作平均移动次数为(n-1)/2,平均时间性能为O(n).

·
·
·
4、线性表的链式存储实现

示意图:

在这里插入图片描述

  • 链式存储实现不要求逻辑上相邻的两个元素在物理位置上也相邻,通过“链“建立起数据元素之间的逻辑关系。
  • (插入、删除不需要移动数据元素,只需要修改链)
  • 缺点:在链表里面,我们只知道链表头,如果想要知道第i个元素在哪里或者是链表的长度是多少,在这两个问题上就比顺序存储要复杂了。

代码:

typedef struct LNode *List;
struct LNode{
	ElementType Data;
	List Next;
};
struct LNode L;
List L;

5、线性表的链式存储的主要操作的实现

  • 求表长
int Length(List L)
{
	List p = L; //p指向表的第一个节点
	int j = 0;      //j是一个计数器
	while (p) {
		p = p->Next;
		j++;
	}
	return j; 
  • 用链表遍历的方法去求得表长,所以时间性能为O(n)。
  • 查找
    (1)按序号查找
List FindKth (int K,List L)
{
	List p = L;
	int i=1;
	while (p!=NULL && i<K ) {
		p = p->Next;
		i++;
	}
	if(i==K) 
		return p;      //找到第K个,返回指针
	else return NULL;
}

(2)按值查找

List FindX(ElementType X,List L)
{
	List p = L;
	while(p != NULL && p->Data !=X)
		p = p->Next;
	return p;
}

平均时间性能为O(n)。

  • 插入(在第i-1 (1<=i<=n+1) 个节点后插入一个值为x的新结点
    代码:
List Insert(ElementType X,int i,List L)
{	
	List p,s;
	if(i==1) {     //新结点插入在表头,申请、填装节点
		s =(List)malloc(sizeof(struct LNode));
		s->Data = X;
		s->Next = L;
		return s;
	}
	p = Findth(i-1,L);
	if(p==NULL){
		printf("参数i错误");
		return NULL;
	}else{
		s =(List)malloc(sizeof(struct LNode)); //申请、填装节点
		s->Data = X;
		s->Next = p->Next;     //新结点插入在第i-1个节点后面
		p->Next = s;
		return L;
	}
}
  • 1、先构造一个新节点,用s指向
  • 2、再找到链表的第i-1个节点,用p指向
  • 3、然后修改指针,插入节点(先将新结点的Next指向i-1后面的节点,再将第i-1个节点指向新的s节点,防止链表的丢失)
  • 平均查找次数为 n/2,平均时间性能为O(n)

示意图:
在这里插入图片描述

  • 删除
    代码实现:
List Delete(int i,List L)
{
	List p,s;
	if(i==1){
		s = L;      //若要删除的是第一个节点,s指向第一个节点,从链表中删除
		if(L!=NULL)  L=L->Next;
		else return NULL;
		free(s);
		return L;
	}
	p = FindKth(i-1,L);
	if(p==NULL){
		printf("第%d个节点不存在,i-1");
		return NULL;
	}else if(p->Next == NULL){
		printf("第%d个节点不存在",i);
		return NULL;
	}else{
		s = p->Next;
		p->Next = s->Next;      //s指向第i个节点,从链表中删除
		free(s);      //释放被删除节点
		return L;
	}
}

  • 1、先找到链表的第i-1个节点,用p指向
  • 2、再用指针s指向要被删除的节点,即p的下一个节点
  • 3、然后修改指针,让p指向s的下一个节点,即删除s所指节点
  • 4、最后释放s所指节点的空间

示意图:
在这里插入图片描述

·
·
·
·
·

附:文中所有PPT图片均来自中国大学mooc 浙江大学《数据结构》课程!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值