2.线性表

问题:一元多项式及其运算,主要运算有:加减乘等…
一 元 多 项 式 前 n 项 和 S n : ∑ n = 0 n a n X n , 与 幂 级 数 ∑ n = 0 ∞ a n X n 不 同 , 幂 级 数 为 lim ⁡ n → + ∞ ∑ n = 0 n a n X n 一元多项式前n项和S_n:\sum_{n=0}^{n}a_nX^n,与幂级数\sum_{n=0}^{\infty}a_nX^n不同,幂级数为\lim_{n\rightarrow+\infty}\sum_{n=0}^{n}a_nX^n nSnn=0nanXnn=0anXnn+limn=0nanXn
1.怎么存储每项元素

2.怎么实现运算

实现1

顺序存储[数组].
P 1 = 1 + 4 x + 7 x 3 P 2 = 4 + 8 x 2 + 6 x 4 P1 = 1+4x+7x^3\\P2 = 4 + 8x^2 +6x^4 P1=1+4x+7x3P2=4+8x2+6x4

Array’s index01234
P1’s array14070
P2’s array40806

这里实现加法逻辑

for(i,i<(p1.len>p2.len?p1.len:p2.len),i++) p3[i] = p1[i]+p2[i]
output:p3

实现2(实现1,存储了多余次数为0项,加法逻辑也做了多余操作,浪费了存储空间,也增加了加法逻辑的时间复杂度。)

改进为顺序结构体存储[结构体数组] struct struc_array{ int an,int x_param} 按x_param系数从小排列
P 1 = 1 + 4 x + 7 x 3 − 11 x 6 P 2 = 4 + 8 x 2 − 6 x 4 − 10 x 5 P1 = 1+4x+7x^3-11x^6\\P2 = 4 + 8x^2 -6x^4 -10x^5 P1=1+4x+7x311x6P2=4+8x26x410x5

P1’s struct_array(1,0)(4,1)(7,3)(-11,6)
P2’s struct_array(4,0)(8,2)(-6,4)(-10,5)
p3(5,0)(4,1)(8,2)(7,3)(-10,5)(-11,6)

实现加法逻辑:

int i = 0, j = 0,k = 0;
begin:循环
if(p1[i].x_param < p2[j].x_param) { p3[k++] = p1[i];i++;} //直接输出x系数小的项
else { p3[k] = p2[j] ; j++;k++;}//和p3[k++] common
if(p1[i].x_param == p2[j].x_param) {p3[k].an = p1[i].an+p2.[j].an;p3.x_param = p1[i].x_param;k++;i++;j++} //x系数相同项相加an
end

实现3:

链式存储一元多项式:

 typedef struct polynomial_node{
	int an;
    int x_param;
    struct polynomial_node *next;
}poly_node;
poly_node* newnode(int an = 0,int x_param = 0){
    poly_node* temp_node = (poly_node*)malloc(sizeof(poly_node))
    temp_node->an = an;
    temp_node->x_param = x_param;
    return temp_node;
}

加法实现逻辑与二相同

链表结点的连接顺序按x_param从小到大连接

循环判断p1链表当前结点与p2链表当前结点的x的指数大小,若相等则将an系数相加,p1当前结点指向下一结点,p2当前结点指向下一节点;若不相等则输出系数小的项,同时系数小的链表的当前结点指向下一结点。若有链表已便利完,则逐个输出另一链表剩余结点所存储的项。

一元多项式可以这样存储那么二元多项式呢

P ( x , y ) = 9 x 1 2 y 2 + 4 x 1 2 + 15 x 8 y 3 − 8 x 1 2 y + 3 x 2 P(x,y) = 9x^12y^2 +4x^12+15x^8y^3-8x^12y+3x^2 P(x,y)=9x12y2+4x12+15x8y38x12y+3x2

我们可以采取线性表存储数据(顺序表没两个单元为一个项的存储单位)或链表数据域中存储x,y\
那么将P(x,y)合并同类项则有
P ( x , y ) = ( 9 y 2 + 4 ) x 1 2 + ( 15 y 3 − y ) x 5 + 3 x 2 P(x,y) = (9y^2+4)x^12+(15y^3-y)x^5+3x^2 P(x,y)=(9y2+4)x12+(15y3y)x5+3x2
这里我们也可采取另一种存储结构广义表(线性表的推广,称其为Lists,表中数据元素由union联合体组成可表示不同结构,故难以用顺序结构存储,常用链式存储结构,)

[外链图片转存失败(img-w18er1mP-1568032452694)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1561276451735.png)]

typedef enum{Atom,List}ElemTag; //Atom(原子) ==0,list(表) ==1
typedef struct s_GLNode{
    ElemTag union_tag;
    union{
        AtomType data; //原子所存储的数据
        struct s_GLNode *hp;//字表的头节点
    };
    struct s_GLNode *next;//GLList的next结点,即主链表
}GLNode,*GList;

[外链图片转存失败(img-uSuja80t-1568032452698)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1561277735539.png)]

多重链表:节点中的指针域会有多个,所以上述广义表就可已是一种多重链表,但广义表所有结点都为tag==0不能算多重链表了。

且包含两个指针域的不能算多重链表,如双向链表(*piror,*next)整个链表还是为一个链表

再由一个问题退出一种新的线性表的推广,十字链表

[外链图片转存失败(img-VPytcblt-1568032452704)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1561279052742.png)]

每一行,列都为一个带头节点的单向循环链表,即第一行和第一列的头节点都为同一个结点,那么二行二列也是,类比n行n列也是

[外链图片转存失败(img-Z2ISSoaE-1568032452709)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1561279239376.png)]

typedef enum{Head,Term}NodeTag; //结点类型0-head,1-term
typedef struct s_MLLM{ //s_Multiple_LinkList_Matrix
    NodeTag tag;
    struct s_MLLM *Dowm;//列指针
    union{
       Row row; //Term结点所在的行
       Col col; //列
       Value value;//存储的值
       struct s_MLLM *Next; //若为头节点则指向下一头节点
    };
    struct s_MLLM *Right;//行指针
}

[外链图片转存失败(img-fPXgPFCP-1568032452710)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1561279617759.png)]

1.线性表(Linear List):由n个相同类型数据元素构成的有限序列的线性结构。

1)表中元素的个数称为线性表的长度

2)表的起始位置为表头(唯一的第一个元素),表的结束位置为表尾(唯一的最后一个元素)

3)除第一个元素外只有一个前驱(表头无前驱),除最后一个元素外元素只有一个后继(表尾无后继)

2.线性表的常用存储存储方式

1)顺序存储(逻辑上相邻,物理上也相邻),线性表的顺序存储实现可称顺序表

​ 优点:可随机存取

​ 缺点:插入,删除操作时需移动大量个元素。

2)链式存储(逻辑上相邻,但不要求物理上相邻),线性表的链式村粗实现可称链表

​ 由n个结点链接而成,每个结点由值域和指针域组成

​ 与顺序表相比,没有了随机存取的优点,同时没有了顺序表的缺点,链表插入,删除时只需修改前一结点指针域。

1.1)顺序表的定义和基本操作的实现

1.Sqlist使用一维数组静态分配,数组大小空间固定
#define Maxsize 10
typedef struct static_Sqlist{
    ElemType data[Maxsize];
    int length;
}Sqlist;
2.Sqlist使用动态分配的一位数组
typedef struct dynamic_Sqlist{
    ElemType *data;
    int length;
}Sqlist;
//初始化内存
Status init(Sqlist &list,int init_size){
    list.data = (ElemType *)malloc(sizeof(ElemType)*init_size);
    list.length = init_size;
}
//申请更多内存
Status more(Sqlist &list,int more_size){
    list.data = (ElemType *)remalloc(list.data,sizeof(ElemType)*more_size);
    list.length += more_size;
}

1.2)插入操作实现

Status insert(Sqlist &list,int i,ElemType e){
    if( i < 1 || i > list.length + 1)//插入位置第一个到最后一个元素的( 1<=i<=l.len+1) 
    	return Error;
    if( list.length >= list.size) return Error;
    for(int j = list.length; j >= i; j--){//移动 n-i+1个元素 循环执行j -i +1次
    	list.data[j] = list.data[j-1];
    }
    list.length++;
    return Ok;

最好时间复杂度:O(1),在表尾插入(即 i = n+1,最后一个元素的后一位)不移动元素
最坏时间复杂度:O(n),在表头插入(即 i = 1 ,第一个元素位置),移动n-1+1,即n个元素。
平均时间复杂度: O(n)设每一位置插入平均概率P=1/n+1(n+1,为插入选择n+1个),累加每一种可能移动的元素个数。
T ( n ) = p ∑ i = 1 n + 1 ( n − i + 1 ) = 1 n + 1 [ n ( n + 1 ) − ( n + 1 + 1 ) ( n + 1 ) 2 + ( n + 1 ) ] = 1 n + 1 n ( n + 1 ) 2 = n 2 T(n)=p\sum_{i=1}^{n+1}(n-i+1)=\frac{1}{n+1}[n(n+1)-\frac{(n+1+1)(n+1)}{2}+(n+1)]=\frac{1}{n+1}\frac{n(n+1)}{2}=\frac{n}{2} T(n)=pi=1n+1(ni+1)=n+11[n(n+1)2(n+1+1)(n+1)+(n+1)]=n+112n(n+1)=2n
1.3)删除操作实现

//i 表示删除的元素的序号(1,2,。。。)
Status delete(Sqlist &list,int i,ElemType &e){
 	   if(i < 1 || i > list.length) return Error; //删除是否合法
	e = list.data[i-1];
 	   for(int j = i;j < list.length; j++ ) //移动n-i元素
 	   		list.data[j-1] = list.data[j];
 	   return Ok;
}

最好时间复杂度:O(1),删除的元素为尾部元素,不需移动元素

最坏时间复杂度: O(n),删除的元素为第一个元素,需移动n-1个元素,T(n) = n-1,故O(n) = n

平均时间复杂度:O(n),删除位置范围(1<=i<=n),设平均插入概率P = 1/n;
T ( n ) = ∑ i = 1 n P ( n − i ) = P ∑ i = 1 n ( n − i ) = 1 n [ n 2 − n ( n + 1 ) 2 ] = n − 1 2 T(n) = \sum_{i=1}^{n}P(n-i) = P\sum_{i=1}^{n}(n-i)=\frac{1}{n}[n^2-\frac{n(n+1)}{2}]=\frac{n-1}{2} T(n)=i=1nP(ni)=Pi=1n(ni)=n1[n22n(n+1)]=2n1
故平均时间复杂度为O(n).

1.4按值查找(顺序查找)
int LoacteElem(Sqlist &list,ElemType e){
    for(int i = 0; i < list.length; i++)
    	if(e == list.data[i]) return i+1; //i为当前位置索引,当前位置则加1
  	return -1;//未找到
}

最好时间复杂度:O(1),判断第一个元素及所找元素。

最坏时间复杂度:O(n),最好一个元素为所找元素,判断次数 T(n) = n

平均时间复杂度:O(n), 查找到的平均概率1/n,T(n) = 1/n * (n+1)n/2 = (n+1)/2,故平均时间复杂度为O(n).

。链表未完。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值