实验(线性

一、实验目的和要求

本次实验的主要目的是为了使学生熟练掌握线性表的基本操作在顺序存储结构和链式存储结构上的实现,提高分析和解决问题的能力。要求仔细阅读并理解下列例题,上机通过,并观察其结果,然后独立完成后面的实习题。


二、实验内容和原理

选做第二题第三题


第二题:

输入:

请输入第一个多项式的系数和指数

请输入多项式的项数:3

请输入第1项的系数:2

请输入第1项的指数:4

请输入第2项的系数:6

请输入第2项的指数:7

请输入第3项的系数:7

请输入第3项的指数:6

请输入第二个多项式的系数和指数

请输入多项式的项数:2

请输入第1项的系数:2

请输入第1项的指数:3

请输入第2项的系数:4

请输入第2项的指数:1

输入的第一个多项式是:

2*X^4  6*X^7  7*X^6

输入的第二个多项式是:

2*X^3  4*X^1

输出:

两个多项式的和为:2*X^3  4*X^1  2*X^4  6*X^7  7*X^6

思路:获取A,B 两个多项式,每获取一个就建立一个结点插入到头结点之后。形成一

个多项式单链表。

创建头结点 C 将A,B 多项式 串联起来。 在操作过程中,一定要 将头结点C 赋值给 pc ,通过pc连接多项式。因为最后要返回 头结点C。

A,B多项式比较指数的大小,小项直接接在pc的后面,若相等,计算系数之和,不为零,保存下来。为零,跳过这个多项式。

最后,将A,B多余的多项式,直接串联在pc后就完成了。

返回头结点 C。


第三题:

输入:

n s m:5 4 1

输出:

输出排序:4 5 1 2 3

存储结构:单项循环链表

算法思想:分析:对于n个人,每一次出列一个人,余下的n-1个人仍然是一个Josephus

问题,因此可以使用递归的方式,每次出列一个人,直到余下最后一个人。

三、主要仪器设备

惠普笔记本,win10环境,皆在cpp文件运行,请同样以cpp形式打开

四、操作方法与实验步骤

第二题: 

#include<stdio.h>
#include<stdlib.h>

typedef struct list{
	int c;//系数 
	int e;//指数 
	struct list *next; 
}list,*Linklist; 

//创建多项式 
Linklist creatPolyn(){
	Linklist  head,p,q;
	int m;
	head = (Linklist)malloc(sizeof(list));
	head->next= NULL;
	q = head;
	printf("请输入多项式的项数:");
	scanf("%d",&m);
	for(int i=0;i<m;i++){
		p = (Linklist)malloc(sizeof(list));
		printf("输入第%d项的系数:",i+1);
		scanf("%d",&p->c);
		printf("输入第%d项的指数:",i+1);
		scanf("%d",&p->e);
		p->next = q->next;
		q->next = p;
		q = q->next;
	}
	return head;
}
//多项式相加 
Linklist AddPolyn(Linklist pa,Linklist pb){
	Linklist a,b,pc,c;
	a = pa;//保存pa的头结点 
	//printf("pa->c = %d pa->e = %d\n",pa->c,pa->e);
	b = pb;//保存pb的头结点 
	//将pa,pb多项式相加的结果保存在c中
	c = (Linklist)malloc(sizeof(list)); //给 C 申请一个空间 
	c->next = NULL; // 生成头结点 
	pc = c;//把头结点 给pc  方便之后操作!如果没有pc这个变量,直接操作c的话,return c 的结果只有最后一项,因为在过程中,c的地址已经发生了变化 
	while(a&&b){
		int m,n,sum;
		m=a->e; n=b->e; // m,n分别保存 a,b的 指数 
		if(m>n){
			pc->next = b;
			pc = pc->next;
			b = b->next;
			//printf("b多项式指数小  %d*X^%d\n",pc->c,pc->e);
		}
		else if(m == n){
			sum = a->c + b->c;
			if(sum!=0){
				a->c = sum;
				pc->next = a;
				pc=pc->next;
				//printf("多项式指数一样大  %d*X^%d\n",pc->c,pc->e);
			}
			//在这里有个 小bug  我不会修改了!bug是: 当两个多项式的最有一项和为0时,计算结果却是,项数多的那个多项式的最后一项 
			//a,b 已经处理完毕,同时后移一位。 
			a = a->next;
			b = b->next;
		}
		else{
			pc->next = a;
			pc = pc->next;
			a = a->next;
			//printf("a多项式指数小  %d*X^%d\n",pc->c,pc->e);
		}
		
	}
	// 判断那个多项式没有走到 NULL  然后将pc->next 直接指向剩余的多项式 
	if(a!=NULL){
		pc->next = a;
	}
	if(b!=NULL){
		pc->next = b;
	}
	return c;
}
void printList(Linklist L){
	while(L != NULL){
		printf("%d*X^%d ",L->c,L->e);
		L = L->next;
	}
	printf("\n"); 
}
int main(){
	Linklist pa,pb,pc;
	printf("请输入第一个多项式的系数和指数\n");
	pa = creatPolyn();
	printf("请输入第二个多项式的系数和指数\n");
	pb = creatPolyn();
	printf("输入的第一个多项式是:\n");
	printList(pa->next);
	printf("输入的第二个多项式是:\n");
	printList(pb->next);
	pc = AddPolyn(pa->next,pb->next);
	printf("两个多项式的和为:");
	printList(pc->next);
	return 0;
}

第三题: 

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <malloc.h>


using namespace std;
typedef struct list//链表
{
	int date;
	struct list *next;
}list,*linklist;
list* l;
void intlist(linklist &l,int n)//构建循环链表
{
	l = (linklist)malloc(sizeof(list));//没有头节点
	l->next = l;
	l->date = 1;
	linklist p;
	for (int i = n; i > 1; i--)
	{
		p= (linklist)malloc(sizeof(list));
		p->next = l->next;
		l->next = p;
		p->date = i;

	}

}
void out(linklist l, int s, int m,int n)//依次出列
{
	list* p = l;
	int i ;
	for (i = 1;; i++)//寻找s的位置
	{
		if (p->date == s)
		{
			break;
		}
		p = p->next;

	}//找出s的位置 p记录

	if (m != 1)//当m不等于一时
	{
		for (int j = 1; j <= n; j++)//有n次出列动作
		{
			if (j == 1)
			{
				for (int h = 1; h < m - 1; h++)
				{
					p = p->next;
				}
			}
			else
			{
				for (int h = 1; h < m; h++)
				{
					p = p->next;
				}
			}
			cout << p->next->date << " ";
			p->next = p->next->next;
		}
	}
	else
	{
		for (int j = 1; j <= n; j++)
		{
			cout << p->date << " ";
			p = p->next;
		}
	}
	
}
int main()
{
	while (1)
	{
		int n, s, m;
		cout << "依次输入n s m:";
		cin >> n >> s >> m;
		if (n < s||n<=0||s<=0||m<=0)
		{
			cout << "输入错误,请重试!" << endl;
			continue;
		}
		intlist(l, n);
		cout << "输出排序:";
		out(l, s, m, n);
		cout << "\n";
	}

	return 0;
}

五、实验数据记录和处理

第二题:

数据结构与算法实验课程信息系统 数据结构与算法实验一_数据结构

第三题:

数据结构与算法实验课程信息系统 数据结构与算法实验一_数据结构与算法实验课程信息系统_02

六、实验结果与分析

第二题:

优点:使用链表,使得增删较为简单。

缺点:没有考虑输入非数字情况

时间复杂度为:O(m+n)

第三题:

优点:采用单项循环链表,使结构较为简单

缺点:采用递归,不使用链表会更加简单

七、讨论、心得

    第三题在分析时发现一种更好的方法,即不使用链表和数组,采用数学公式用递归

方法即可写出,只需七行即可

约瑟夫环问题满足公式f(n,m)=[f(n−1,m)+m]%nf(n,m)=[f(n−1,m)+m]%n

int josephRing ( int sum, int value, int n)
 {
     if ( n == 1 )
         return ( sum + value - 1 ) %sum;
     else
         return ( josephRing ( sum-1, value,n-1 ) +value ) %sum;
 }

通过两个实验,对于链表的理解不再是纸上谈兵,而是可以做简单的实验题了,在编写

代码中遇到种种问题,但都通过调试解决了,其中在调试时也收获许多。