一、内容和要求
1、实现单链表,包括单链表的生成,元素插入,删除操作
2、使用单链表存储两个集合元素,并且实现集合的并运算,输出并的结果,结果不能有重复元素
3、使用单链表实现多项式相加
二、解决方案和关键代码
首先如何理解类:类是一种自定义数据类型的方法。
int A
这里定义了一个int类型的变量A,那么A就可以储存整型的数据。
char B
同理,变量B可以储存字符型的数据。
class Node {
public:
float data1;//系数
float data2;//幂次
Node* next;
};
int main() {
Node* List1 = NULL;
}
类也同样如此,这里定义了一个新的类型叫做Node,它可以存储三个数据。当我们在main函数中定义一个Node类型的指针变量叫List1,我们就可以在里面储存三个数据。
定义所需的类
创建链表
首先要求输入要创建多项式有多少项,即可知 for 循环的次数。
需要注意的是:需要保留第一个节点的地址,否则创建好了单链表,找不到第一个,后面的都将找不到。所 以需要把“创建第一个节点”这个过程单独拎出来,创建好第一个节点后要复制一份放在一边,创建好整个单链 表后,只需通过第一个节点即可找到整个单链表。
因为已创建第一个节点,后面 for 循环的次数减 1 即可。
for 循环内容:
创建一个新的盒子,怎么样的盒子?——类定义的盒子。
输入系数和幂次,分别赋值给新盒子的 data1 和 data2。
将新盒子的地址赋值给上一个盒子的 next 部分,即可通过上一个盒子找到下一个盒子。
void creatlist(Node* &P,int &length) {
P = new Node;
Node* newnode; Node* head = NULL; Node* prenode = NULL;
cout << "请输入多项式项数:" << endl;
cin >> length;
if (length > 0) {
// 创建首个节点
head = new Node;
cout << "请输入第1项的系数和幂次:" << endl;
cin >> head->data1 >> head->data2;
head->next = NULL;
prenode = head;
}
P = head;
// 循环创建其余节点
for (int i = 1; i < length; i++) { // 注意这里从1开始,因为首个节点已经创建
newnode = new Node;
cout << "请输入第" << i + 1 << "项的系数和幂次:" << endl;
cin >> newnode->data1 >> newnode->data2;
newnode->next = NULL;
prenode->next = newnode;
prenode = newnode; // 移动到新的节点
}
}
增加链表
创建一个新的盒子,输入 data1 和 data2,将链表第一个节点的地址赋值给新盒子的 next。相对于在多项式 的最前面插入一项。
void insertlist(Node*&P,int &length) {
Node* newnode=NULL;
newnode = new Node;
cout << "请输入要插入的系数和次幂:" << endl;
cin >> newnode->data1 >> newnode->data2;
newnode->next = P;
P = newnode;
length++;
}
删除链表
采用 for 循环移动到要删除的地方,如何知道 for 循环的次数?——要求输入要删除第几项,即可知 for 循环 的次数。
需要注意的是几种特殊情况:单链表长度小于输入的项数该怎么办?刚好要删除第一个节点怎么办?单链表 的长度为 1 该怎么办?如果要删除队尾怎么办?
void deletelist(Node*&P,int& length) {
int n;
Node* lastnode = NULL; Node* nextnode = NULL; Node* nownode=NULL;
lastnode = new Node;
nownode = new Node;
nextnode = new Node;
cout << "请输入想要删除第几项:" << endl;
cin >> n;
if (n<=0 && n>length)//输入的项数错误
{
cout << "输入的项数有误,请重新输入:" << endl;
}
else//输入的项数正确
{//移动第一步,nownode指向第1个节点
nownode = P;
nextnode = P->next;
lastnode->next = nownode;
if (n == 1&&length==1) {//如果要删除第1项或链表长度为1,那直接删除
P = P->next;
delete nownode;
length--;
}
else//否则就要循环至要删除的地方
{
for (int i = 1; i < n; i++) {
nextnode = nextnode->next;
nownode = nownode->next;
lastnode = lastnode->next;
}//此时已循环至要删除的地方
if (n == length) {//如果要删除的是队尾
lastnode->next = NULL;
delete nextnode;
delete nownode;
length--;
}
else//如果要删除的不是队尾
{
lastnode->next = nextnode;
delete nownode;
length--;
}
}
}
}
整理链表
需要将同幂次的项合并,那只需判断每一个盒子的 data2 部分是否相同,相同则将 data1 合并,然后释放这 片空间。
计划采用四个指针:一个指着等待合并其他盒子的盒子。其他三个指针,一个指着目前正在比对的盒子,其他 两个分别指着“正在比对的盒子的前一个盒子”和“正在比对的盒子的后一个盒子”;只要发现等待合并其他盒子 的盒子与正在比对的盒子的 data2 相同,那就将正在比对的盒子的 data1 加到等待合并其他盒子的盒子的 data1, 然后将正在比对的盒子删去,将下一个盒子的地址赋值给上一个盒子的 next 部分。
需要注意的是几种特殊情况:如果单链表长度为 1 怎么办?如果正在比对的盒子是最后一个怎么办?for 循环 的次数是一成不变的吗?
void sortlist(Node* P,int&length) {
Node* head = NULL; Node* nownode = NULL; Node* lastnode = NULL; Node* nextnode = NULL;
head = new Node;
lastnode = new Node;
nownode = new Node;
nextnode = new Node;
head->next = P;
for (int i = 1; i < length; i++) {//合并同幂次的项
head = head->next;
nownode = head->next;
lastnode = head;
nextnode = nownode->next;
for (int j = 0; j < length-1 ; j++) {
if (nownode->data2 == head->data2) {//如果幂次相等
head->data1 += nownode->data1;
if (nownode->next == NULL) {//如果此节点是最后一个节点
delete nownode;
delete nextnode;
lastnode->next = NULL;
}
else {//如果此节点不是最后一个节点
lastnode->next = nextnode;
nownode = nextnode;
nextnode = nextnode->next;
}
length--;
}
else//如果幂次不相等
{
if (nownode->next == NULL) {//如果下一个节点为空,跳出
break;
}
else//如果下一个节点不为空,指针移动
{
nextnode = nextnode->next;
nownode = nownode->next;
lastnode = lastnode->next;
}
}
}
}
}
合并链表
需要创立第三个链表,然后将前两个链表依次赋值给第三个的链表即可。
需要注意的事跟创建链表情况 一样,需要保留第三个链表第一个节点的地址,否则找不到第三个链表。
void sumlist(Node*List1,int length1, Node*List2,int length2,Node*&List3,int &length3) {
length3 = 0;
Node* nownode = NULL; Node* lastnode = NULL;
lastnode = new Node;
List3 = new Node;
List3->data1 = List1->data1;
List3->data2 = List1->data2;
List3->next = NULL;
lastnode = List3;
nownode = List3;
length3++;
if (length1 == 1) {//如果长度为1,则停止
}
else//如果长度不为1,则接龙
{
List1 = List1->next;
for (int i = 0; i < length1 - 1; i++) {
nownode = new Node;
nownode->data1 = List1->data1;
nownode->data2 = List1->data2;
nownode->next = NULL;
List1 = List1->next;
lastnode->next = nownode;
lastnode = nownode;
length3++;
}
}
for (int i = 0; i < length2; i++) {
nownode = new Node;
nownode->data1 = List2->data1;
nownode->data2 = List2->data2;
nownode->next = NULL;
List2 = List2->next;
lastnode->next = nownode;
lastnode = nownode;
length3++;
}
}
输出链表
void exportlist(Node*head) {
if (head == NULL) {
cout << "多项式不存在!" << endl;
}
Node* temp = NULL;
temp = new Node;
temp = head;
while (temp != NULL) {
cout << temp->data1 << "x^" << temp->data2;
if (temp->next != NULL) {
cout << "+";
}
temp = temp->next;
}
if (temp == NULL) {
cout << endl;
}
}
主函数
int main() {
int length1 = 0;
int length2 = 0;
int length3 = 0;
int n;
Node* List1 = NULL;
Node* List2 = NULL;
Node* List3 = NULL;
cout << "请先创建多项式!" << endl;
creatlist(List1, length1);
sortlist(List1, length1);
exportlist(List1);
creatlist(List2, length2);
sortlist(List2, length2);
exportlist(List2);
while (1) {
cout << "请选择要执行的程序:1、插入多项式 2、删除多项式某项 3、多项式相加 其他:退出" << endl;
cin >> n;
switch (n)
{
case 1:
cout << "第1个多项式为";
exportlist(List1);
cout << "第2个多项式为";
exportlist(List2);
cout << "请选择要插入的多项式:" << endl;
cin >> n;
switch (n) {
case 1:
insertlist(List1, length1);
sortlist(List1, length1);
cout << "修改后多项式为:";
exportlist(List1);
break;
case 2:
insertlist(List2, length2);
sortlist(List2, length2);
cout << "修改后多项式为:";
exportlist(List2);
break;
}
break;
case 2:
cout << "第1个多项式为";
exportlist(List1);
cout << "第2个多项式为";
exportlist(List2);
cout << "请选择要删除的多项式:" << endl;
cin >> n;
switch (n) {
case 1:
deletelist(List1, length1);
cout << "删除后第1个多项式为";
exportlist(List1);
break;
case 2:
deletelist(List2, length2);
cout << "删除后第2个多项式为";
exportlist(List2);
break;
}
break;
case 3:
sumlist(List1, length1, List2, length2, List3, length3);
sortlist(List3, length3);
cout << "合并后多项式为:";
exportlist(List3);
break;
default:
return 0;
}
}
}