线性表的应用举例

一元多项式的表示及相加

1、一元多项式的表示:

一元多项式可按升幂的形式写成:
P n ( x ) P_n(x) Pn(x) = p 0 p_0 p0 + p 1 p_1 p1 x 1 x^1 x1 + p 2 p_2 p2 x 2 x^2 x2 + … + p n p_n pn x n x^n xn P i P_i Pi是指数i项的系数.
一元多项式 Q m ( x ) Q_m(x) Qm(x)可用线性表Q来表示.
Q= ( q 0 q_0 q0 q 1 q_1 q1 q 2 q_2 q2, …, q n q_n qn).
若m < n,则两个多项式相加的结果 R n ( x ) R_n(x) Rn(x)= P n ( x ) P_n(x) Pn(x) + Q m ( x ) Q_m(x) Qm(x),也可用线性表R来表示:
R=( p 0 p_0 p0+ q 0 q_0 q0 p 1 p_1 p1+ q 1 q_1 q1,…, p m p_m pm+ q m q_m qm p m + 1 p_{m+1} pm+1,…, p n p_n pn).

2、一元多项式的存储

(1)一元多项式的顺序存储表示

法1:使用数组只存储多项式各项系数,系数对应的指数项则隐含在顺序表的下标中。
即p[0]存 x 0 x^0 x0的系数 p 0 p_0 p0,p[i]存 x i x^i xi的系数 p i p_i pi,……p[n]存 x n x^n xn的系数 p n p_n pn,下标即指数。
这种存储方法使得多项式相加运算的算法定义十分简单
只需将下标相同的单元的内容相加即可。
适合于存储表示非零系数多的多项式。

法2:只存储非零项。
每个非零项需要存储:系数和对应指数。
适合存储表示非零项少的多项式。

(2)一元多项式的链式存储表示

只存非零项:每项数据由两部分构成(指数项系数项),外加指针项。
在这里插入图片描述
① 结点结构定义如下:

type struct Polynode 
{
	int coef;
    int exp;
    Polynode *next;
}Polynode,* Polylist

② 建立一元多项式链式存储的算法:

键盘输入一组多项式的系数和指数,输入系数0时结束,尾插法建链表,并按指数从小到大的顺序排列。

Polylist  polycreate(Polylist head)
{
 	Polynode *rear,*s;
	int c,e;
	rear=head=(Polynode *)malloc(sizeof(Polynode));  //头结点,rear链尾
	scanf("%d,%d",&c, &e);  /*键入多项式的系数和指数项*/
	while(c!=0) /*若c=0,则多项式输入结束*/
	{
	 	s = (Polynode *)malloc(sizeof(Polynode));	/*申请新结点*/
    	s->coef=c; 
		s->exp=e; 
		rear->next=s ;	/*表尾插入*/
    	rear=s; 	
		scanf("%d,%d", &c, &e);
	}
 	rear->next = NULL;  /*最后结点next置NULL*/
    return(head);
 }

③ 两个一元多项式相加

算法实现:p、q分别指向多项式链A、B第一结点,结果存到A链。
p->exp < q->exp:结点p应是“和多项式”中的一项,A链p后移;
p->exp > q->exp:结点q应是“和多项式”中的一项,将其插入p结点前,q在B链上后移;
p->exp == q->exp:两结点系数相加,和不为零则修改结点p的系数域,释放结点q;若和为零,则从A链中删去结点p,同时释放p和q结点。

void  polyadd(Polylist polya; Polylist polyb) //合并polyb到polya中
{
	Polynode *p, *q, *tail=polya;*temp; //新链尾
	int sum;
	p = polya->next;
	q = polya->next;
	while(p!=NULL && q!=NULL)
	{	if(p->exp < q->exp)   /*尾插结点p*/
		{
			tail->next = p;
		    tail = p; 
			p = p->next;
		}
   		else if (p->exp == q->exp)//指数相等系数相加
   		{
		   	if((sum = p->coef + q->coef) != 0)
			{
				p->coef = sum; 
				tail->next = p; //p系数更新
				tail = p; p = p->next; //尾插p结点
				temp = q; q = q->next;
			    free(temp);//删除q结点并后移 
			}
			else /*系数和为零,则删除结点p与q,并移动p、q*/
			{
				temp=p; p=p->next; free(temp);	
				temp=q; q=q->next; free(temp);
			}
   		else
		{
		   tail->next=q; tail=q; q = q->next; /*将q结点加入到和多项式中*/  
		}
	} 
	if(p!=NULL) 
	    tail->next=p; /*A有剩余,加入到和多项式中*/
	else 
	    tail->next=q;
}  /*将B剩余结点加入到和多项式中*/

在这里插入图片描述

在这里插入图片描述

顺序表 删除指定范围

题目:设计一个高效的算法,从顺序表L中删除所有值介于x和y之间(包括x和y)的所有元素(假设y>=x),要求时间复杂度为O(n),空间复杂度为O(1)。

struct _seqlist{
    ElemType elem[MAXSIZE];
    int last;
};
typedef struct _seqlist SeqList;

void del_x2y(SeqList* L, ElemType x, ElemType y)
{
    int i = 0, j = 0;
    for (i = 0; i < MAXSIZE; i++) 
    {
        if (L->elem[i] < x || L->elem[i] > y) 
            L->elem[j++] = L->elem[i];
    }
    L->last=j;
}

顺序表 删除重复

编写算法,在一非递减的顺序表L中,删除所有值相等的多余元素。要求时间复杂度为O(n),空间复杂度为O(1)。

struct _seqlist{
    ElemType elem[MAXSIZE];
    int last;
};
typedef struct _seqlist SeqList;

void del_dupnum(SeqList* L)
{
    int i = 0, j = 0;
    ElemType demo = L->elem[0];
    L->elem[j++] = L->elem[0];
    for (i = 1; i < L->last; i++) 
    {
        if (L->elem[i] != demo) 
        {
            L->elem[j++] = L->elem[i];
            demo = L->elem[i];
        }
    }
    L->last = j;
}

顺序表 数据调整

已知顺序表L中的数据元素类型为int。设计算法将其调整为左右两部分,左边的元素(即排在前面的)均为奇数,右边所有元素(即排在后面的)均为偶数,并要求算法的时间复杂度为O(n),空间复杂度为O(1)。

struct _seqlist{
    ElemType elem[MAXSIZE];
    int last;
};
typedef struct _seqlist SeqList;

void odd_even(SeqList* L)
{
    ElemType demo = L->elem[0];
    int i = 1, temp, j = 0;
    for (; i < L->last; i++)
     {
        j = i;
        if (L->elem[i] % 2 != 0) //交换顺序
         {
            temp = L->elem[i];
            L->elem[i] = demo;
            demo = temp;
            i = j;
        }
    }
}

链表 删除范围内结点

已知线性表中的元素(整数)以值递增有序排列,并以单链表作存储结构。试写一高效算法,删除表中所有大于mink且小于maxk的元素(若表中存在这样的元素),分析你的算法的时间复杂度。

struct _lnklist{
    ElemType data;
    struct _lnklist *next;
};
typedef struct _lnklist Node;
typedef struct _lnklist *LinkList;

void lnk_del_x2y(LinkList L, ElemType mink, ElemType maxk)
{
    Node *pre, *r;
    pre = L;
    while (pre->next != NULL && pre->next->data <= mink) {
        pre = pre->next;
    }
    
    while (pre->next != NULL && pre->next->data < maxk) {
        r = pre->next;
        pre->next = r->next;
        free(r);
    }
}

链表 倒数查找

已知一个带有表头结点的单链表, 假设链表只给出了头指针L。在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,函数通过指针参数 p_ele 返回该结点 data 域的值,此时函数返回 1;否则,函数返回 0。

struct _lnklist{
    ElemType data;
    struct _lnklist *next;
};

typedef struct _lnklist Node;
typedef struct _lnklist *LinkList;

int lnk_search(LinkList L, int k, ElemType* p_ele)
{
    Node *p, *r;
    r = L;
    p = L->next;
    int i = 1;
    while (p != NULL) {
        p = p->next;
        i++;
        if (i > k) {//p和r之间的距离已经有k了,现在呢就要保持k的距离
            r = r->next;
        }
    }
    if (r == L) {
        return 0;
    } else {
        *p_ele = r->data;
        return 1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值