概念:线性表是零个或多个数据元素组成的有限序列。
☼特点:线性表的元素是有序的
若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其余的元素有一个前驱和一个后继
线性表强调是有限的
线性表插入操作:
•如果插入位置不合理,抛出异常。
•如果线性表长度大于等于数组长度,则抛出异常或动态增加数组容量。
•从最后一个元素开始向前遍历到第i个元素,分别将它们都向后移动一个位置。
•将要插入元素填入位置i处。
•线性表长为1。
线性表(单链表)的读取:
获得链表第i个数据的算法思路:
•声明一个节点p指向链表第一个节点,初始化j从1开始
•当j<i时,就遍历链表,让p的指针向后移动,不断指向下一节点,j+1。
•若到链表末尾p为空,则说明第i个元素不存在,否则查找成功,返回节点p的数据。
链表的优点在于链表实现了真正的动态存储,不需要关心存储容量的问题。缺点在于它失去了随机访问的能力。
这是链表的节点定义:
public class list<E> {
//首先定义一个private修饰,只能在linkedlist类内访问的内部类存储节点信息
private class Node{
public E e;
public Node next;
}
//多态,根据用户传来的参数个数不同
public Node(E e,Node next){
this.e=e;
this.next=next;
}
public Node(E e){
this(e,null);
}
public Node(){
this(null,null);
}
@Override
public String toString(){
return e.toString;
}
}
向链表中一个一个地添加元素将这些节点挂接起来:
应用:一元多项式运算器:
一元多项式在计算机中存储时仅需要存储非0的系数项。为了实现任意多项式的运算,考虑到运算中有较多的插入删除操作,选择单链表作为存储结构比较方便,每个节点有3个域:系数,指数,指针。其数据结构如下所示:
typedef struct Polynomial{
float coef; //系数
int expn; //指数
struct Polynomail *next; //指向下一个节点的指针
};
多项式计算器的算法实现如下:
1.建立多项式
通过键盘输入一组多项式的系数和指数,用尾插法建立一元多项式的链表。以输入系数0为结束标志,并约定建立一元多项式链表时,总是按指数从小到大的顺序排列。
2.输出多项式
从单链表第一个元素开始,逐项读出系数和指数,安多项式的形式进行输出即可。
3.两个多项式相加
以单链表pa和pb分别表示两个一元多项式A和B,A+B的求和运算,就等同于单链表的求和问题
4.相减
將减数pb多项式的所有系数变成其相反数,然后使用两个多项式相加思想进行处理
5.多项式乘法
多项式乘法类似于将两个多项式相加,pa*pb,需要使用pb多项式中的每一项和pa多项式中的每一项进行相乘,然后进行多项式相加操作。
6.求多项式的值,需要输入变量x的值然后进行求职计算。
7.多项式的导数
需要根据导数公式对多项式的每一个节点求导,具体过程如下:
需要根据导数公式对多项式的每一个结点求导,具体过程如下:多项式当前结点指数为0,则其导数的系数为当前结点指数乘以系数,指数为当前节点的指数减1。
以下,是课本上给出的算法(C语言描述)
//建立多项式
Polyn CreatePoly(){
Polynomial *head,*rear,*s;
int c,e;
head=(Polynomial *)malloc(sizeof(Polynomial)); //建立多项式头结点
rear=head; //始终指向单链表的尾,便于尾插法建表
scanf("%d,%d",&c,&e);//键入多项式的系数和指数项
while(c!=0){ //若c=0,则代表多项式输入结束
s=(Polynomial*)malloc(sizeof(Polynomial));
s->coef=c;
s->expn=e;
rear->next=s; //在当前表尾插入
rear=s;
scanf("%d,%d",&c,&e);
}
rear->next=NULL;//将表中最后一个节点的next置为null
return(null);
}
//输出多项式
void PrintPolyn(Polyn P){
Polyn q=p->next;
int flag=1;
if(!q){
putchar('0');
printf("\n");
return;
}
while(q){
if(q->coef>0&&flag!=1) putchar('+');
if(q->coef!=1&&q->coef!=-1){
printf("%g",q->coef);
if(q->expn==1) putchar('X');
else if(q->expn) printf("X^%d",q->expn);
}else{
if(q->coef==1)
{
if(q->coef==1){
if(!q->expn) putchar('1');
else printf("X^%d",q->expn);
}
if(q->coef==-1){
if(!q->expn)printf("-1");
else if(q->expn==1) printf("-X");
else printf("-X%d",q->expn);
}
}
q=q->next;
flag++;
}
}
printf("\n");
}
//两个多项式相加
Polyn AddPolyn(Polyn pa,Polyn pb){
Polyn qa=pa->next;
Polyn qb=pb->next;
Polyn headc,pc,qc;
pc=(Polyn)malloc(sizeof(struct Polynomial)); //单链表pc用于保存pa+pb的和
pc->next=NULL;
headc=pc;
while(qa!=NULL&&qb!=NULL) //当两个多项式均未扫描结束时
{
qc=(Polyn)malloc(sizeof(struct Polynomial));
if(qa->expn<qb->expn){
qc->ceof=qa->ceof;
qc->expn=qa->expn;
qa=qa->next;
}
else if(qa->expn>qb->expn){
qc->ceof=qa->ceof+qb->ceof;
qc->expn=qa->expn;
qa=qa->next;
qb=qb->next;
}
else{
qc->ceof=qb->ceof;
qc->expn=qb->expn;
qb=qb->next;
}
if(qc->ceof!=0)
{
qc->next=pc->next;
pc->next=qc;
pc=qc;
}else free(qc);
}
//pa中如果有剩余项,就将剩余项插入到pc当中
while(qa!=null)
{
qc=(Polyn)malloc(sizeof(struct Polynomial));
qc->ceof=qa->ceof;
qc->expn=qa->expn;
qa=qa->next;
qc->next=pc->next;
pc->next=qc;
pc=qc;
}
//pb中如果有剩余项,就将剩余项插入到pc当中
while(qb!=null)
{
qc=(Polyn)malloc(sizeof(struct Polynomial));
qc->ceof=qb->ceof;
qc->expn=qb->expn;
qb=qb->next;
qc->next=pc->next;
pc->next=qc;
pc=qc;
}
return headc;
}
//两个多项式相减
Polyn substractPolyn(Polyn pa,Polyn pb)
{
Polyn h=pb;
Polyn p=pb->next;
Polyn pd;
while(p)
{
p->coef*=-1;
p=p->next;
}
pd=AddPolyn(pa,h);
for(p=h->next;p;p=p->next)
p->ceof*=-1;
return pd;
}
找到链表的倒数第n个结点
分析:从表头节点开始遍历链表,让M表示链表的长度。得到长度后,计算M-n+1的值,然后从表头再遍历一遍就得到链表的长度。然后链表再从头遍历一次就能得到第M-n+1个结点。这个方法需要两次遍历:一次用于求链表的长度,另一次用于寻找从表头开始的第M-n+1个结点。