赞
踩
本期正式步入数据结构
本篇文章是学习视频中的笔记
参考视频 [浙江大学数据结构(陈越、何钦铭)](数据结构_中国大学MOOC(慕课) (icourse163.org))
多项式的关键数据
1、多项式项数n
2、各项系数ai以及指数i
数组各分量对应多项式各项:
两个多项式相加:两个数组对应分量相加
但是问题是:如何表示多项式x+3x^2000?
显然我们要用2001个分量表示,但其实只有两项是非零的,这样会造成空间的巨大浪费
所以虽然这种方法表示方便,但仍有很大的问题,于是引入第二种方法
基本思路:只表示非零项
每个非零项 aix^i 涉及两个信息:系数ai和指数i,可以将一个多项式看成是一个(ai,i)二元组的集合
我们这里也可以用数组表示,但每个分量就不能简单只是系数了,而且要包含指数
用结构数组表示:数组分量是由系数ai、指数i组成的结构,对应一个非零项。
这种方法是否计算方便呢?
只要我们按指数大小有序存储,仍然是非常容易的
例如两个多项式相加
先定位到两个多项式的第一项,比较两个定位点对应的项,较大的这一项提取出来,并使该定位点后移,另一个定位点不变,继续比较两个定位点对应的项,循环以上操作,直到其中一个多项式的项全部遍历,然后将另一个多项式剩余项按序排放。
链表中每个结点存储多项式中的一个非零域,包括系数和指数两个数据域以及一个指针域
排列的时候我们仍然按指数大小有序存储即可
对应的结构定义可以这样写
typedef struct PolyNode *Polynomial:
struct PolyNode{
int coef;
int expon;
Polynomial link;
}
例如仍是上面的P1(x)和P2(x)
定义:线性表是由同类型数据元素构成有序序列的线性结构
类型名称:线性表(List)
数据对象集:线性表是n(>=0)个元素构成的有序序列(a1,a2,… ,an)
操作集:线性表L∈List,整数i表示位置,元素X∈ElementType
利用数组的连续存储空间顺序存放线性表的各元素
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
初始化(建立空顺序表)
List MakeEmpty()
{
List PtrL;
PtrL = (List)malloc(sizeof(struct LNode));
PtrL->Last = -1;
return PtrL;
}
查找
int Find( ElementType X,List PtrL )
{
int i = 0;
while(i<=PtrL->Last && PtrL->Data[i]!=X)
i++;
if(i>PtrL->Last) //没找到
return -1;
else //找到了
return PtrL;
}
//查找成功的平均比较次数为(n+1)/2,平均时间性能为O(n)
插入( 第 i(1 =< i <= n+1)个位置上插入一个值为X的新元素)
//现移动,再插入 //从后往前挪 void Insert( ElementType X,int i,List PtrL) { int j; if(PtrL->Last == MAXSIZE-1){ printf("表满"); return; } if(i<1||i>PtrL->Last+2){ printf("位置不合法"); return; } for(j = PtrL->Last;j>=i-1;j--) PtrL->Data[j+1]=PtrL->Data[j]; //将ai到an倒序后移 PtrL->Data[i-1] = X; //新元素插入 PtrL->Last++; //Last仍指向最后元素 return; } //平均移动次数为n/2,平均时间性能为O(n)
删除
//现移动,再插入 //从后往前挪 void Delete( int i, List L ) { int j; if(i<1||i>PtrL->Last+1){ //检查空表及删除位置的合法性 printf("不存在第%d个元素",i); return; } for(j = i;j<=PtrL->Last;j++) //将a(i+1)到 an 顺序前移 PtrL->Data[j-1]=PtrL->Data[j]; PtrL->Last--;//Last仍指向最后元素 return; } //平均移动次数为(n-1)/2,平均时间性能为O(n)
不要求逻辑上相邻的两个元素物理上也相邻;通过“链”建立起数据元素之间的逻辑关系。
typedef struct LNode *List;//定义指向链表指针
struct LNode{
ElementType Data;
List Next;
};
struct Lnode L;
List PtrL;
求表长
int Length( List PtrL )
{
List p = PtrL; //p指向表的第一个结点
int j = 0;
while(p){ //条件:p不等于NULL
p = p->Mext;
j++;
}
return j;
}
//时间性能为O(n)
查找
(1)按序号查找:FindKth
List FindKth(int K,List PtrL)
{
List p = PtrL; //p指向表的第一个结点
int i = 1;
while(p!=NULL&&i<K)
{
p=p->Next;
i++;
}
if(i== K)
return p;
else
return NULL;
}
//平均时间性能O(n)
(2)按值查找:Find
List Find(ElementType X,List PtrL){
List p = PtrL;
while(p!=NULL && p->Data != x)
p = p->Next;
return p;
}
//平均时间性能O(n)
插入( 第 i(1 =< i <= n+1)个位置上插入一个值为X的新元素)
步骤:
注意顺序(1) s->Next=p->Next;(2) p->Next=s;
List Insert(ElementType X,int i ,List PtrL){ List p,s; //第1个位置插入,表头地址改变 if(i == 1){ s = (List)malloc(sizeof(struct LNode)); s->Data = X; s->Next = PtrL; return s; //返回新的头结点地址 } p = Findkth(i-1,PtrL); //返回第i-1结点地址 //p不存在 if(p == NULL){ printf("参数i错"); return NULL; }else{ s = (List)malloc(sizeof(struct LNode)); s->Data = X; s->Next = p->Next; p->Next = s; return PtrL; //返回头结点地址(头指针不变) } } //平均查找次数n/2
删除( 删除第 i(1 =< i <= n)个位置上的结点 )
步骤:
List Delete(int i,List PtrL){ List p,s; if(i == 1){ s = PtrL; //为了释放内存所以保存 if(Ptrl!=NULL) PtrL = PtrL->Next; else return NULL; free(s); return PtrL; } p = Findkth(i-1,PtrL); //返回第i-1结点地址 //判断指针p的合法性(是否前一个不存在或是结点i不存在) 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; free(s); return PtrL; } }
我们知道了一元多项式的表示,那么二元多项式如何表示?
比如,给定二元多项式
如何表示呢?
分析:将上述二元多项式看成关于x的一元多项式
所以可以用“复杂”链表表示为:
typedef struct GNode *GList;
struct GNode{
int Tag; //标志域:0表示结点是单元素,1表示结点是广义表
union{ //子表指针域SubList与单元素数据域Data复用,即共用存储空间
ElementType Data;
GList SubList;
}URegion;
GList Next; //指向后继结点
};
我们在构造时可能会碰到一个问题:一个域有可能是不能分解的单元,有可能是一个指针
C语言有一种手段,union。union可以把不同类型的数据组合在一起,可以把这个空间理解成某种类型,也可以理解为另外一种类型
如何区分不同类型?
一般的方法是设一个标记,即Tag来区分后面的空间是Data还是SubList
多重链表:链表中的节点可能同时隶属于多个链
多重链表有广泛用途:基本上树、图这样相对复杂的数据结构都可以采用多重链表方式实现存储
矩阵可以用二维数组表示,但二维数组表示有两个缺陷:
分析:采用一种典型的多重链表——十字链表来存储稀疏矩阵
只存储矩阵非0元素项
结点的数据域:行坐标Row、列坐标Col、数值Value
每个结点通过两个指针域,把同行、同列串起来
头节点的标识值为“Head“,矩阵非0元素结点的标识值为”Term“
对应结构如下:
给出一个矩阵A
链表图如下
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。