数据结构第二章线性表经典例题及一元稀疏多项式实现分享

经典例题:

例1:设计一个高效的算法,从顺序表L中删除所有值为x的元素,要求时间复杂度为O(n),空间复杂度为O(1)。

算法思想:为了实现一个高效的算法,我们不采用从头开始扫描顺序表,遇到值为x的元素就将其删除的方法,因为删除运算需要将删除元素后到表尾的元素前移,时间复杂度为O(n),这样会导致整个问题的复杂度为O(n²)。我们采用的方法是在原表的空间内重建一个顺序表,主要思想是:设置两个指示器i和j,i用来记录正在扫描到的原表中的元素的位置,j用来记录当前正在建立的新表表尾的下一个位置,i和j的初值为0。这样根据L->elem[i]是否等于x来做不同的处理。若L->elem[i]!=x,则L->elem[j]=L->elem[i],i++,j++;若L->elem[i]==x,则i++。因为每次都是在新表的表尾插入元素,所以避免了移动元素的代价,从而达到了时间复杂度为O(n)。

实现代码:

void delx(SeqList *L,ElemType x){
	i=0;j=0;
	while(i<=L->last){
		if(L->elem[i]!=x){
			L->elem[j]=L->elem[i];
			i++;j++;
		}
		else
			i++;
	}
	L->last=j-1;
}

例2:算法实现带头结点单链表的就地逆置问题

算法思想:

就地逆置不需要额外申请结点空间,只需要利用原有的表中的结点空间即可。若对顺序表中的元素进行逆置,可以借助“交换”前后相应元素的方法实现。对单链表中的元素进行逆置,则不能按“交换”思路。因为假设链表长度为n,则对于链表中第i个结点需要顺链查找第n-i+1个结点,逆置链表的时间复杂度将达O(n²)。这里采用的方法为:将逆置后的单链表初始化为空表,“删除”原链表中第一个结点,然后将它插入到逆置链表的“表头”,然后从原链表中依次“摘下”结点,再逐个以头插法放置到逆置单链表表头结点和表中第一个结点之间。

实现代码:

void ReverseList(LinkList L){	//逆置带头结点的单链表L
	p=L->next;	//p为原链表的当前处理结点
	L->next=NULL;	//逆置单链表初始为空表
	while(p!=NULL){	//当原链表未处理完
		q=p->next;	//q指针保留原链表当前处理结点的下一个结点
		
		//将当前处理结点p插入到逆置表L的表头
		p->next=L->next;	
		L->next=p;
		
		p=q;	//p指向下一个待插入的结点
	}
}

例3:已知带头结点的单链表L,设计算法实现:以表中第一元素作为标准,将表中所有值小于第一个元素的结点均放在第一结点之前,所有值大于第一元素的结点均放在第一元素结点之后。

代码实现:

void ChangeList(LinkList L){
	if(L->next==NULL)
		return ERROR;
	p1=L->next;	//p1指向表中第一元素
	pre=p1;
	p=p1->next;
	
	/*顺次从p开始取结点,比p1->data小的插在头结点之后,
    比p1->data大的结点不作处理,继续检测其后继结点*/
	while(p){
		q=p->next;
		if(p->data>=p1->data){
			pre=p;
			p=q;
		}
		else{
			pre->next=p->next;
			p->next=L->next;
			L->next=p;
			p=q;
		}
	}
}

例4:建立一个带头结点的线性链表,用以存放输入的二进制数,链表中每个结点的data域存放一个二进制位。并在此链表上实现对二进制数加1的运算。

算法思想:

①建链表:二进制数可用带头结点的单链表存储,第一个结点存储二进制数的最高位,依次存储,最后一个结点存储二进制数的最低位。②二进制加法规则:实现二进制数加1运算,方向从低位往高位找到第一个值为0的位,从该位开始,对后面所有低位进行求反运算。③链表实现二进制加1时,从高位往低位与运算方向正好相反,从第一个结点开始找,找出最后一个值域为0的结点,把该结点值域赋为1,其后所有结点的值域赋为0。④若在链表中为找到值域为0的结点,则表示该二进制数各位均为1,此时,申请一新结点,值域为1,插入到头结点与原链表的第一个结点之间,成为新链表的第一个结点,其后所有结点的值域赋为0。

代码实现:

void BinAdd(LinkList l){	//用带头结点的单链表L存储二进制数,实现加1运算
	Node *q,*r,*s;
	q=l->next;
	r=1;
	while(q!=NULL){	//查找最后一个值域为0的结点
		if(q->data==0)
			r=q;
		q=q->next;
	}
	if(r!=1)
		r->data=1;	//将最后一个值域为0的结点的值域赋为1
	else{	//未找到值域为0的结点
		s=(Node *)malloc(sizeof(Node));	//申请新结点存放最高进位
		s->data=1;	//值域赋为1
		s->next=L->next;
		L->next=s;	//插入到头结点之后
		r=s;
	}
	r=r->next;
	while(r!=NULL){	//将后面的所有结点的值域赋为0
		r->data=0;
		r=r->next;
	}
}

一元稀疏多项式实现:

程序还存在一定的不足,后续会不断完善功能,有不对的地方还请各位多多包涵并指正,有好的建议或者想法也可以私信我交流,谢谢大家~

以下是程序运行结果示例:

按0进行多项式输入:

按4进行多项式相加:

 按5进行多项式相减:

 按1、2、3进行多项式值计算:

源码如下:

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<conio.h>
#include<windows.h>
#define bool int
#define true 1
#define false 0
double coefs[80];  
int expns[80]; 
int cnt, m;


double get_coef(char *str)  
{
	double s = 0.0;
	double d = 10.0;
	bool flag = false;
	while (*str == ' ')  str++;
	if (*str == '-')  
	{
		flag = true;  
		str++;
		if (*str == 'x') 	return -1.0;
	}
	else if ((*str == '+'&&*(str + 1) == 'x') || (*str == 'x'))  return 1.0;
	if (*str == '+' && (*(str + 1) >= '0'&&*(str + 1) <= '9'))  str++;
	if (!(*str >= '0'&&*str <= '9'))     return s; 
	while (*str >= '0'&&*str <= '9'&&*str != '.')
	{
		s = s * 10.0 + *str - '0';
		str++;
	}
	if (*str == '.')    str++;          
	while (*str >= '0'&&*str <= '9')  
	{
		s = s + (*str - '0') / d;
		d *= 10.0;
		str++;
	}
	return s * (flag ? -1.0 : 1.0);
}

void getNums()
{
	int i = 0;
	cnt = 0;
	double coef;
	int expn;
	char str[80];
	scanf("%s", str);
	while (*(str + i))
	{
		coef = get_coef(str + i);
		if (*(str + i) != 'x') i++;
		while ((*(str + i) >= '0'&&*(str + i) <= '9') || (*(str + i) == '.'))  	i++;
		if (*(str + i) == '+' || *(str + i) == '-' || *(str + i) == '\0')	expn = 0;
		else if (*(str + i) == 'x')
		{
			i++;
			if (*(str + i) == '+' || *(str + i) == '-' || *(str + i) == '\0') 
				expn = 1;
			else if (*(str + i) == '^')
			{
				i++;
				expn = (int)get_coef(str + i);
				while ((*(str + i) >= '0'&&*(str + i) <= '9') || (*(str + i) == '.'))
					i++;
			}
		}
		coefs[cnt] = coef;
		expns[cnt] = expn;
		cnt++;
	}
}

typedef struct Polynomial   //多项式
{
	double coef; //系数
	int expn;   //指数
	struct Polynomial *next;  //指针
} Polynomial, *Polyn;  //创建一个头指针为head,项数为m的一元多项式

//建立链表,在插入过程中实现单链表有序
void CreatPolyn(Polyn head, int m)  
{
	for(int i = 0; i < m; i++)
	{
		Polyn p = (Polyn)malloc(sizeof(struct Polynomial));  
		//将数组中的系数和指数存进链表
		p->coef = coefs[i];    
		p->expn = expns[i];   
		if(p->coef == 0) free(p);
		else
		{
			Polyn q1, q2;
			q1 = head;
			q2 = head->next;
			while(q2 != NULL && p->expn > q2->expn)
			{
				q1 = q2;
				q2 = q2->next;
			}
			if(q2 != NULL && p->expn == q2->expn)
			{
				q2->coef += p->coef;
				if(q2->coef == 0)
				{
					q1->next = q2->next;
					free(q2);
				}
				free(p);
			}
			else
			{
				p->next = q2;
				q1->next = p;
			}
		}
	}
}

//进行格式化打印输出
void printPoLlyn(Polyn head) 
{
	Polyn q = head->next;
	int flag = 0; 
	if(!q)
	{
		puts("NULL(0)\t");
		return;
	}
	while(q)
	{
		if(q->coef > 0 && flag == 1)
		{
			printf("+");
		}
		flag = 1;
		if(q->coef != 1 && q->coef != -1)
		{
			printf("%g", q->coef);
			
			if (q->expn == 1) printf("x");
			else if(q->expn != 0) printf("x^%d", q->expn);
		}
		else
		{
			if(q->coef == 1)
			{
				if(q->expn == 0)  printf("1");
				else if (q->expn == 1) printf("x");
				else printf("x^%d", q->expn);
			}
			if(q->coef == -1)
			{
				if(q->expn == 0) printf("-1");
				else if(q->expn == 1) printf("-x");
				else printf("-x^%d", q->expn);
			}
		}
		q = q->next;
	}
	printf("\t\t");
}

//比较两个多项式是否为同类项 
int compare(Polyn a, Polyn b)
{
	if(a&&b)
	{
		if(a->expn > b->expn) return 1;
		else if(a->expn < b->expn) return -1;
		else return 0;
	}
	else if(!a&&b) return -1;
	else if(a && !b) return 1;
	else if(!a && !b)return 0;
}


void clear(Polyn c)
{
	Polyn p, q;
	p = c;
	while(p->next != NULL)
	{
		q = p->next;
		p->next = q->next;
		free(q);
	}
	c->next = NULL;
}

//多项式相加
void addPolyn(Polyn a1, Polyn b1, Polyn c1)  
{
	Polyn a = a1;
	Polyn b = b1;
	Polyn c = c1;
	clear(c1);
	Polyn head, qc;
	Polyn qa = a->next;
	Polyn qb = b->next;
	head = c;
	while(qa || qb)
	{
		qc = (Polyn)malloc(sizeof(Polynomial));
		if(compare(qa, qb) == 1)
		{
			qc->coef = qa->coef;
			qc->expn = qa->expn;
			qa = qa->next;
		}
		else if(compare(qa, qb) == 0)
		{
			qc->coef = qa->coef + qb->coef;
			qc->expn = qa->expn;
			qa = qa->next;
			qb = qb->next;
		}
		else
		{
			qc->coef = qb->coef;
			qc->expn = qb->expn;
			qb = qb->next;
		}
		
		if(qc->coef != 0) 
		{
			qc->next = c->next;
			c->next = qc;
			c = qc;
		}
	}
}

// 多项式相减
void subPolyn(Polyn a, Polyn b, Polyn c)
{
	Polyn h = b;
	Polyn p = b->next;
	while(p)
	{
		p->coef *= -1;
		p = p->next;
	}
	addPolyn(a, h, c);
	for(Polyn i = h->next; i != 0; i = i->next)
	{
		i->coef *= -1;
	}
}


void goto_xy(int x, int y)
{
	HANDLE hOut;
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(hOut, pos);
}

//计算x的值
void value(Polyn head, int flag)  
{
	goto_xy(2, 3); printf(" 请输入x = ");
	double sum = 0, x;
	scanf("%lf", &x);
	for(Polyn p = head->next; p != 0; p = p->next)
	{
		double tmp = 1;
		int expn = p->expn;
		while (expn != 0)
		{
			if (expn < 0)      tmp /= x, expn++;
			else if (expn > 0) tmp *= x, expn--;
		}
		sum += p->coef*tmp;
	}
	goto_xy(2, 4);
	if(flag == 1) printf(" A( %g )的值 = %g", x, sum);
	if(flag == 2) printf(" B( %g )的值 = %g", x, sum);
	if(flag == 3) printf(" C( %g )的值 = %g", x, sum);
}

//界面实现
void show(Polyn a, Polyn b, Polyn c) 
{
	goto_xy(0, 0); 	 printf("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
	goto_xy(0, 1);   printf("┃            一元稀疏多项式简单计算器             ┃\n");
	goto_xy(0, 2);   printf("┃━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 3);   printf("┃\n"); goto_xy(50, 3);                    printf("┃\n");
	goto_xy(0, 4);   printf("┃\n"); goto_xy(50, 4);                    printf("┃\n");
	goto_xy(0, 5);   printf("┃\n"); goto_xy(50, 5);                    printf("┃\n");
	goto_xy(0, 6);   printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 7);   printf("┃★ A :"); goto_xy(7, 7); printPoLlyn(a);  goto_xy(50, 7);  printf("┃");
	goto_xy(0, 8);   printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 9);   printf("┃★ B :"); goto_xy(7, 9); printPoLlyn(b);  goto_xy(50, 9);  printf("┃");
	goto_xy(0, 10);  printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 11);  printf("┃★ C :"); goto_xy(7, 11); printPoLlyn(c);  goto_xy(50, 11);  printf("┃");
	goto_xy(0, 12);  printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 13);  printf("┃   按0进行多项式输入     ┃   按1计算多项式A的值  ┃\n");
	goto_xy(0, 14);  printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 15);  printf("┃   按2计算多项式B的值    ┃   按3计算多项式C的值  ┃\n");
	goto_xy(0, 16);  printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 17);  printf("┃   按4进行多项式相加     ┃   按5进行多项式相减   ┃\n");
	goto_xy(0, 18);  printf("┣━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━┫");
	goto_xy(0, 19);  printf("┃   按t退出多项式计算器   ┃   按enter执行确定换行 ┃\n");
	goto_xy(0, 20);  printf("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
	goto_xy(2, 3);
}

//建立两个多项式A、B
void create(Polyn a1, Polyn b1)   
{
	Polyn a = a1;
	Polyn b = b1;
	clear(a1);
	clear(b1);
	goto_xy(2, 3); printf("请输入多项式A :  ");   getNums();
	m = cnt;
	CreatPolyn(a, m);
	goto_xy(2, 4); printf("请输入多项式B :  ");	  getNums();
	m = cnt;
	CreatPolyn(b, m);
}

//主程序
int main()
{
	Polyn a = (Polyn)malloc(sizeof(struct Polynomial)); a->next = NULL;
	Polyn b = (Polyn)malloc(sizeof(struct Polynomial)); b->next = NULL;
	Polyn c = (Polyn)malloc(sizeof(struct Polynomial)); c->next = NULL;
	char ch, ch1;
	while (1)
	{
		system("cls");
		show(a, b, c);
		ch = _getch();
		if (ch == '0')
		{
			create(a, b);
		}
		
		else if (ch == 't')
		{
			exit(0);
		}
		else if (ch == '1')
		{
			value(a, 1);
			ch1 = _getch();
		}
		else if (ch == '2')
		{
			value(b, 2);
			ch1 = _getch();
		}
		else if (ch == '3')
		{
			value(c, 3);
			ch1 = _getch();
		}else if (ch == '4')
		{
			addPolyn(a, b, c);
		}
		else if (ch == '5')
		{
			subPolyn(a, b, c);
		}
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你代码有bug!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值