数据结构
一、线性表
线性表其实很简单,就是一条线的关系,除了最前面和最后的结点,每一个结点前面都有一个结点,叫前驱,每一个结点后面也有一个结点,叫后继。不过世上的事情都是很灵活的,你也可以把最后一个结点和最前一个结点链接起来,那样就成一个环了,那就叫循环链表。
typedef char Element;
typedef struct {
Element e;
int cur;//游标,相当于链表的next
} Node;
typedef struct {
Node str[MAX];
int length;
} List;
//一些操作函数
void printList(List *a)
{
int i =a->str[MAX-1].cur; //第一个存在数据的结点
for( ; i ; i = a->str[i].cur)
printf("%c ",a->str[i].e);
}
Element enterElem(void)
{
Element c;
while ((c=getchar()) ==' ') ;//把空格去掉
return c;
}
int staMalloc(List *a)
{//把备用链表的结点取出来,就像删除操作一样
int pos = a->str[0].cur; //等于第一个没用到的结点,当没有可用结点的时候,就是cur等于0,不用特别处理
a->str[0].cur = a->str[pos].cur; //指向原本的第二个备用结点
return pos;
}
void initialList(List *a)
{//注意要倒数两个要都要指向0,因为考虑到是两个独立链表,当链表满的时候,继续增加元素会怎样 ,当然,如果是写成循环链表就不用
int i;
for ( i=0; i<MAX-2; ++i)
a->str[i].cur = 1+i;
a->length = a->str[i].cur = a->str[i+1].cur = 0; //0的就相当于链式储存里面的NULL
}
void creatList(List *a)
{//静态链表由两部分组成,一个链表是存放空闲结点都链表(用0),还有一个是用来存放数据的链表(用MAX-1),这里采用头结点插入
Element e;
int i,j=MAX-1;
while ( (e=enterElem()) != '\n') {
if(!(i = staMalloc(a))) {
puts("no more space!!!");
return ;
}
a->str[i].cur = a->str[j].cur;//新结点指向第一个数据结点的位置
a->str[j].cur = i; //在把头结点的cur指向插入的结点
a->str[i].e = e;
++a->length;
}
}
void staFree(List *a,int pos)
{ //收回结点,就是把pos插入备用链表中
a->str[pos].cur = a->str[0].cur;
a->str[0].cur = pos;
}
int findPos(List *a,int pos)
{ //找到链表的第pos个元素并返回它的位置
if ( pos<0 || pos>a->length)
return 0;
int i = 0,j=MAX-1;
for ( ; i<pos; ++i) //从0开始到pos-1,刚好就是第pos个,因为从头结点,所以i从0开始,表示现在是第i个,一直累加
j = a->str[j].cur;
return j;
}
void deletePos(List *a, int pos)
{
int p = findPos(a,pos-1),t; //先找到第pos-1个元素的位置,找前驱,方便删除操作
t = a->str[p].cur; //要删除的元素
a->str[p].cur = a->str[t].cur; //pos的前驱指向pos的后继,跳过pos
staFree(a,t); //释放pos
--a->length;
}
int insertPos(List *a,int pos,Element e)
{
int i = findPos(a,pos-1),j,k;//一样先找到哦啊pos-1,这样方便链表的链接
j = staMalloc(a);
if(i&&j) { //如果找不到pos-1元素或者没有备用结点,那么就不止行,直接return 0了
a->str[j].cur = a->str[i].cur;
a->str[i].cur = j;
a->str[j].e = e;
return 1;
}
return 0;
}
————————————————————————————————————————————————————————————————————————————
下面再来一个纯种的链式储存的例子:
list.h
typedef int Elem;
typedef struct Node{
Elem e;
struct Node *next;
} Node;
typedef struct List {
Node *head;
int length;
} List;
void initialList(List *list);//初始化链表,建立头结点。
void creatList(List *list);//建立链表
void printList(List *list);//打印链表
void cleanList(List *list);//清空链表
int listLength(List *list);//返回链表的长度
int isEmpty(List *list);//判断链表是否为空
Node* posNode(List *list,int pos);//找出第pos个结点,并返回地址
Node* findElem(List *list,Elem e);//找出第一个element是e 的结点,并返回地址
int posToX(List *list,int pos,Elem e);//把第pos个结点的值改为X
void addAtFront(List *list,Elem e);//在链表头部插入
void addAtRear(List *list,Elem e);//在链表尾部插入
int insertPos(List *list,int pos,Elem e);//把e插入链表 ,并使其成为第pos个元素
Elem deletePos(List *list,int pos);//删除第pos个元素,并返回element的值
void deleteX(List *list,Elem e);//删除链表中所有element为e的结点
void swapPosPos(List *list,int pos1,int pos2);//交换结点
void destroyList(List *list);//销毁
list.c
#include<stdlib.h>
#include<stdio.h>
#include"List.h"
int enterElem(Elem *e)
{ //输入<0就放回0,表示输入结束
scanf("%d",e);
if(*e<0)
return 0;
return 1;
}
void initialList(List *list)
{
list->head=(Node *)malloc(sizeof(Node)); //建立头结点
list->head->next=NULL;
list->length = 0;
}
//建立链表,输入小于0代表链表输入终止
void creatList(List *list)
{
Elem e;
Node *p = list->head;
while(enterElem(&e)) {
//尾结点插入
p->next = (Node*)malloc(sizeof(Node));
p=p->next;
p->e = e;
++list->length;
}
p->next = NULL;//处理尾结点的next指向
}
void printList(List *list)
{
Node *p=list->head->next;
while(p) {
printf("%d ",p->e);
p = p->next;
}
}
void cleanList(List *list)
{
Node *p = list->head->next;//指向第一个数据结点
Node *temp;
while(p) {
//把空间free掉
temp=p->next;
free(p);
p = temp;
}
list->length = 0;
list->head->next = NULL;
}
int listLength(List *list)
{
return list->length;
}
int isEmpty(List *list)
{ //返回1就是空,返回0就是不空
return list->length > 0 ? 0 : 1;
}
Node* posNode(List *list,int pos)
{
int i=0;
Node *p=list->head;
if(pos<0 || pos > list->length)//pos允许为0,这样才能对第一个存放数据的结点进行一些操作,但pos是0的时候,将会放回头结点
return NULL;
while (++i <= pos) //找到第pos个
p=p->next;
return p;
}
Node* findElem(List *list,Elem e)
{
Node *p = list->head->next;
while(p)
if ( p->e == e)
return p;
else
p = p->next;
return NULL;
}
int posToX(List *list,int pos,Elem e)
{ //返回1就是修改成功
Node *p = posNode(list,pos);
if (p) {
p->e = e;
return 1;
}
return 0;
}
void addAtFront(List *list,Elem e)
{
Node *p = (Node*)malloc(sizeof(Node));
p->e = e;
p->next = list->head->next;
list->head->next = p;
}
void addAtRear(List *list,Elem e)
{
Node *p = list->head;
while(p->next)
p = p->next;
p->next = (Node*)malloc(sizeof(Node));
p = p->next;
p->e = e;
p->next = NULL;
}
int insertPos(List *list,int pos,Elem e)
{
Node *p = (Node*)malloc(sizeof(Node)),*temp;
p->e = e;
if(temp = posNode(list,pos-1)) {//找前驱
//注意下面这两行的顺序不能掉转哦
p->next = temp->next; //新结点指向第pos个
temp->next = p; //成为第pos个
return 1;
}
return 0;
}
Elem deletePos(List *list,int pos)
{
Node *p,*t;
Elem e;
if(p=posNode(list,pos-1)) {//找前驱
t=p->next; //t指向要删除的结点
e = t->e; //e记住要删除的数据,到时返回
p->next = t->next; //前驱绕过要删除的结点
free(t);
return e;
}
return -1;
}
void deleteX(List *list,Elem e)
{
Node *p = list->head,*tmp;
while(p->next) //一直循环,当遍历完或者找到e为止
if(p->next->e == e) {
tmp = p->next;
p->next = tmp->next;
free(tmp);
}
else
p = p->next;
}
void swapPosPos(List *list,int pos1,int pos2)
{
Node *p1,*p2,*t1,*t2;
//先找到这两个位置的前驱,这样方便操作,t1,t2是指向要交换的结点
//交换结点就是两个结点的前驱next交换,两个结点的next交换
if((p1=posNode(list,pos1-1)) && (p2=posNode(list,pos2-1))){
t1 = p1->next; t2 = p2->next;
//因为记录了t1,t2,所以两个前驱的next直接交换
p1->next = t2;
p2->next = t1;
//当p1是临时指针,用来交换t1,t2的next指针
p1 = t1->next;
t1->next = t2->next;
t2->next = p1;
}
}
void destroyList(List *list)
{
cleanList(list);
free(list->head);
既然写出了,那么就在用这个结构来做一个简单的多项式相加吧。要怎么做呢?首先就是应该来定义个结构体来表示一个项啦,就是说有系数和指数。那么就是每个结点包含的就是系数、指数,还有指向下一个结点的指针。在多项式相加的时候,是次数相同的项,系数相加,不相同的就插进去就可以了。也就是说,我要同时遍历两个多项式的链表,对它们的次数进行比较,如果是相同就系数相加,如果是乱序的话很难做,因为那个不相等,可是可能不知什么地方就有个结点啊,这样的话每次都要遍历另一条链表一次,做起来又麻烦又慢。最好还是有序的,这样就方便多啦。那么就是说在创建链表的时候就要把它创建成有序的,而又不应该这样要求用户输入成有序的。那么怎么做呢?想一下,用类似归纳法的思想想一下,先假定成有序的了,然后再读取一个结点进去,要插入,这样要怎么做呢?就一直遍历下去,直到遇到有一个结点的次数比新结点的次数小或者相等就可以啦。在那里停住的话插入不好搞,所以就是要找符合结点的前驱,这样插入就很简单啦。这个问题想清楚了,还有个问题就是两条表插来插去的具体要怎么做的问题。因为我们是合并它们俩,所以我们只需要把它们的next指针改啊改,然它们串起来就可以了,好就这么定了
#include<stdio.h>
#include<stdlib.h>
typedef struct {
float coef;//系数
int expn;//指数
} Date;
typedef struct Node {
Date x;
struct Node *next;
} Node;
typedef struct {
Node *head;
} List;
void insert(List *L,Node *n,Node *s);
void creatList(List *L);
void addList(List *L1,List *L2,List *L3);
void printList(List *L);
int main(void)
{
List L1,L2,L3;
/******************************************************
用freopen这个函数很方便,不用测试的时候每次都自己输入
输入格式是4,7 3,5...然后以一个字符结尾表示输入完了,因为
输入的时候我是用scanf,那么出现字符的时候就会输入失败
*******************************************************/
freopen("test","r",stdin);
creatList(&L1);
printList(&L1);
creatList(&L2);
printList(&L2);
addList(&L1,&L2,&L3);
printList(&L3);
return 0;
}
void insert(List *L,Node *p,Node *s)
{//p是要插入的结点,s是符合要求的结点的前驱,就下面两句,一插就行啦
p->next = s->next;
s->next = p;
}
void creatList(List *L)
{
Node *p,*s;
int coef,expn;
s = L->head = (Node*)malloc(sizeof(Node));//创建头结点
L->head->next = NULL;
while(scanf("%d,%d",&coef,&expn)) {
while(s->next!=NULL && s->next->x.expn >= expn) {
//这个就是找到符合要求结点前驱的循环
s = s->next;
if(s->x.expn==expn) {
s->x.coef += coef;
break;
}
}
//然后就是给它找个空间,把东西放进去,再插入
p = (Node*)malloc(sizeof(Node));
p->x.coef = coef;
p->x.expn = expn;
insert(L,p,s);
}
getchar();//把代表输入结束的那个字符处理掉
}
void addList(List *L1,List *L2,List *L3)
{
Node *p1,*p2,*p3,*tmp;
p3 = L3->head = L1->head;
p1 = L1->head->next;
p2 = L2->head->next;
while(p1&&p2) {
//指数大的进去L3那条表
if(p1->x.expn > p2->x.expn) {
p3->next = p1;
p3 = p1;
p1 = p1->next;
} else if (p1->x.expn < p2->x.expn) {
p3->next = p2;
p3 = p2;
p2 = p2->next;
} else {
//想等的话就系数加起来,当然,还要考虑如果系数相加等于0要怎么办
//加了之后,p2的结点就没有用了,把它free掉吧
p1->x.coef += p2->x.coef;
tmp = p2;
p2 = p2->next;
free(tmp);
if(p1->x.coef < 0.000001) {//因为是浮点数
//相加之后系数为0,那么p1也没用了,更新p1,把它free掉
tmp = p1;
p1 = p1->next;
free(tmp);
}
}
}
p3->next = p1?p1:p2;//把剩下还没插进去的链表都插进去
}
void printList(List *L)
{
Node *p = L->head->next;
while(p) {
printf("%.2fx^%d+",p->x.coef,p->x.expn);
p = p->next;
}
puts("\b ");//先退一下格,在打印个空格上去,把尾部的+处理掉
}
一、线性表
线性表其实很简单,就是一条线的关系,除了最前面和最后的结点,每一个结点前面都有一个结点,叫前驱,每一个结点后面也有一个结点,叫后继。不过世上的事情都是很灵活的,你也可以把最后一个结点和最前一个结点链接起来,那样就成一个环了,那就叫循环链表。
其实我们想一下,在编程的时候,对于一组数据我们的存储方式其实也就那么两种,一种是数组(这叫顺序储存),另一种就是动态分配内存,然后用一个指针把动态分配的各个空间链接起来(这叫链式储存)。对于链表的实现,我们也是只有这两种存储方式。对于一个数据结构,我们不单止要定义它是怎么构成的,还应该定义一些作用于它的操作,至于编程细节实现就因情况而异了。
以下是一个用数组来模拟链式储存的例子:
在这个例子中,大概的思想是这样的:因为要模拟链表,所以就肯定要知道下一个可以用的结点是哪一个啦,不像顺序储存直接知道,所以我们需要两个链表,一个是用来管理存放数据的链表,另一个就是用来管理所有还没用到的链表,所以需要两个头结点,这里我们就选用一头一尾这两个结点,头的是用来管理备用结点链表的,尾的是用来管理存放数据结点链表的。typedef char Element;
typedef struct {
Element e;
int cur;//游标,相当于链表的next
} Node;
typedef struct {
Node str[MAX];
int length;
} List;
//一些操作函数
void printList(List *a)
{
int i =a->str[MAX-1].cur; //第一个存在数据的结点
for( ; i ; i = a->str[i].cur)
printf("%c ",a->str[i].e);
}
Element enterElem(void)
{
Element c;
while ((c=getchar()) ==' ') ;//把空格去掉
return c;
}
int staMalloc(List *a)
{//把备用链表的结点取出来,就像删除操作一样
int pos = a->str[0].cur; //等于第一个没用到的结点,当没有可用结点的时候,就是cur等于0,不用特别处理
a->str[0].cur = a->str[pos].cur; //指向原本的第二个备用结点
return pos;
}
void initialList(List *a)
{//注意要倒数两个要都要指向0,因为考虑到是两个独立链表,当链表满的时候,继续增加元素会怎样 ,当然,如果是写成循环链表就不用
int i;
for ( i=0; i<MAX-2; ++i)
a->str[i].cur = 1+i;
a->length = a->str[i].cur = a->str[i+1].cur = 0; //0的就相当于链式储存里面的NULL
}
void creatList(List *a)
{//静态链表由两部分组成,一个链表是存放空闲结点都链表(用0),还有一个是用来存放数据的链表(用MAX-1),这里采用头结点插入
Element e;
int i,j=MAX-1;
while ( (e=enterElem()) != '\n') {
if(!(i = staMalloc(a))) {
puts("no more space!!!");
return ;
}
a->str[i].cur = a->str[j].cur;//新结点指向第一个数据结点的位置
a->str[j].cur = i; //在把头结点的cur指向插入的结点
a->str[i].e = e;
++a->length;
}
}
void staFree(List *a,int pos)
{ //收回结点,就是把pos插入备用链表中
a->str[pos].cur = a->str[0].cur;
a->str[0].cur = pos;
}
int findPos(List *a,int pos)
{ //找到链表的第pos个元素并返回它的位置
if ( pos<0 || pos>a->length)
return 0;
int i = 0,j=MAX-1;
for ( ; i<pos; ++i) //从0开始到pos-1,刚好就是第pos个,因为从头结点,所以i从0开始,表示现在是第i个,一直累加
j = a->str[j].cur;
return j;
}
void deletePos(List *a, int pos)
{
int p = findPos(a,pos-1),t; //先找到第pos-1个元素的位置,找前驱,方便删除操作
t = a->str[p].cur; //要删除的元素
a->str[p].cur = a->str[t].cur; //pos的前驱指向pos的后继,跳过pos
staFree(a,t); //释放pos
--a->length;
}
int insertPos(List *a,int pos,Element e)
{
int i = findPos(a,pos-1),j,k;//一样先找到哦啊pos-1,这样方便链表的链接
j = staMalloc(a);
if(i&&j) { //如果找不到pos-1元素或者没有备用结点,那么就不止行,直接return 0了
a->str[j].cur = a->str[i].cur;
a->str[i].cur = j;
a->str[j].e = e;
return 1;
}
return 0;
}
————————————————————————————————————————————————————————————————————————————
下面再来一个纯种的链式储存的例子:
list.h
typedef int Elem;
typedef struct Node{
Elem e;
struct Node *next;
} Node;
typedef struct List {
Node *head;
int length;
} List;
void initialList(List *list);//初始化链表,建立头结点。
void creatList(List *list);//建立链表
void printList(List *list);//打印链表
void cleanList(List *list);//清空链表
int listLength(List *list);//返回链表的长度
int isEmpty(List *list);//判断链表是否为空
Node* posNode(List *list,int pos);//找出第pos个结点,并返回地址
Node* findElem(List *list,Elem e);//找出第一个element是e 的结点,并返回地址
int posToX(List *list,int pos,Elem e);//把第pos个结点的值改为X
void addAtFront(List *list,Elem e);//在链表头部插入
void addAtRear(List *list,Elem e);//在链表尾部插入
int insertPos(List *list,int pos,Elem e);//把e插入链表 ,并使其成为第pos个元素
Elem deletePos(List *list,int pos);//删除第pos个元素,并返回element的值
void deleteX(List *list,Elem e);//删除链表中所有element为e的结点
void swapPosPos(List *list,int pos1,int pos2);//交换结点
void destroyList(List *list);//销毁
list.c
#include<stdlib.h>
#include<stdio.h>
#include"List.h"
int enterElem(Elem *e)
{ //输入<0就放回0,表示输入结束
scanf("%d",e);
if(*e<0)
return 0;
return 1;
}
void initialList(List *list)
{
list->head=(Node *)malloc(sizeof(Node)); //建立头结点
list->head->next=NULL;
list->length = 0;
}
//建立链表,输入小于0代表链表输入终止
void creatList(List *list)
{
Elem e;
Node *p = list->head;
while(enterElem(&e)) {
//尾结点插入
p->next = (Node*)malloc(sizeof(Node));
p=p->next;
p->e = e;
++list->length;
}
p->next = NULL;//处理尾结点的next指向
}
void printList(List *list)
{
Node *p=list->head->next;
while(p) {
printf("%d ",p->e);
p = p->next;
}
}
void cleanList(List *list)
{
Node *p = list->head->next;//指向第一个数据结点
Node *temp;
while(p) {
//把空间free掉
temp=p->next;
free(p);
p = temp;
}
list->length = 0;
list->head->next = NULL;
}
int listLength(List *list)
{
return list->length;
}
int isEmpty(List *list)
{ //返回1就是空,返回0就是不空
return list->length > 0 ? 0 : 1;
}
Node* posNode(List *list,int pos)
{
int i=0;
Node *p=list->head;
if(pos<0 || pos > list->length)//pos允许为0,这样才能对第一个存放数据的结点进行一些操作,但pos是0的时候,将会放回头结点
return NULL;
while (++i <= pos) //找到第pos个
p=p->next;
return p;
}
Node* findElem(List *list,Elem e)
{
Node *p = list->head->next;
while(p)
if ( p->e == e)
return p;
else
p = p->next;
return NULL;
}
int posToX(List *list,int pos,Elem e)
{ //返回1就是修改成功
Node *p = posNode(list,pos);
if (p) {
p->e = e;
return 1;
}
return 0;
}
void addAtFront(List *list,Elem e)
{
Node *p = (Node*)malloc(sizeof(Node));
p->e = e;
p->next = list->head->next;
list->head->next = p;
}
void addAtRear(List *list,Elem e)
{
Node *p = list->head;
while(p->next)
p = p->next;
p->next = (Node*)malloc(sizeof(Node));
p = p->next;
p->e = e;
p->next = NULL;
}
int insertPos(List *list,int pos,Elem e)
{
Node *p = (Node*)malloc(sizeof(Node)),*temp;
p->e = e;
if(temp = posNode(list,pos-1)) {//找前驱
//注意下面这两行的顺序不能掉转哦
p->next = temp->next; //新结点指向第pos个
temp->next = p; //成为第pos个
return 1;
}
return 0;
}
Elem deletePos(List *list,int pos)
{
Node *p,*t;
Elem e;
if(p=posNode(list,pos-1)) {//找前驱
t=p->next; //t指向要删除的结点
e = t->e; //e记住要删除的数据,到时返回
p->next = t->next; //前驱绕过要删除的结点
free(t);
return e;
}
return -1;
}
void deleteX(List *list,Elem e)
{
Node *p = list->head,*tmp;
while(p->next) //一直循环,当遍历完或者找到e为止
if(p->next->e == e) {
tmp = p->next;
p->next = tmp->next;
free(tmp);
}
else
p = p->next;
}
void swapPosPos(List *list,int pos1,int pos2)
{
Node *p1,*p2,*t1,*t2;
//先找到这两个位置的前驱,这样方便操作,t1,t2是指向要交换的结点
//交换结点就是两个结点的前驱next交换,两个结点的next交换
if((p1=posNode(list,pos1-1)) && (p2=posNode(list,pos2-1))){
t1 = p1->next; t2 = p2->next;
//因为记录了t1,t2,所以两个前驱的next直接交换
p1->next = t2;
p2->next = t1;
//当p1是临时指针,用来交换t1,t2的next指针
p1 = t1->next;
t1->next = t2->next;
t2->next = p1;
}
}
void destroyList(List *list)
{
cleanList(list);
free(list->head);
}
————————————————————————————————————————————————————————————————————————————
既然写出了,那么就在用这个结构来做一个简单的多项式相加吧。要怎么做呢?首先就是应该来定义个结构体来表示一个项啦,就是说有系数和指数。那么就是每个结点包含的就是系数、指数,还有指向下一个结点的指针。在多项式相加的时候,是次数相同的项,系数相加,不相同的就插进去就可以了。也就是说,我要同时遍历两个多项式的链表,对它们的次数进行比较,如果是相同就系数相加,如果是乱序的话很难做,因为那个不相等,可是可能不知什么地方就有个结点啊,这样的话每次都要遍历另一条链表一次,做起来又麻烦又慢。最好还是有序的,这样就方便多啦。那么就是说在创建链表的时候就要把它创建成有序的,而又不应该这样要求用户输入成有序的。那么怎么做呢?想一下,用类似归纳法的思想想一下,先假定成有序的了,然后再读取一个结点进去,要插入,这样要怎么做呢?就一直遍历下去,直到遇到有一个结点的次数比新结点的次数小或者相等就可以啦。在那里停住的话插入不好搞,所以就是要找符合结点的前驱,这样插入就很简单啦。这个问题想清楚了,还有个问题就是两条表插来插去的具体要怎么做的问题。因为我们是合并它们俩,所以我们只需要把它们的next指针改啊改,然它们串起来就可以了,好就这么定了
#include<stdio.h>
#include<stdlib.h>
typedef struct {
float coef;//系数
int expn;//指数
} Date;
typedef struct Node {
Date x;
struct Node *next;
} Node;
typedef struct {
Node *head;
} List;
void insert(List *L,Node *n,Node *s);
void creatList(List *L);
void addList(List *L1,List *L2,List *L3);
void printList(List *L);
int main(void)
{
List L1,L2,L3;
/******************************************************
用freopen这个函数很方便,不用测试的时候每次都自己输入
输入格式是4,7 3,5...然后以一个字符结尾表示输入完了,因为
输入的时候我是用scanf,那么出现字符的时候就会输入失败
*******************************************************/
freopen("test","r",stdin);
creatList(&L1);
printList(&L1);
creatList(&L2);
printList(&L2);
addList(&L1,&L2,&L3);
printList(&L3);
return 0;
}
void insert(List *L,Node *p,Node *s)
{//p是要插入的结点,s是符合要求的结点的前驱,就下面两句,一插就行啦
p->next = s->next;
s->next = p;
}
void creatList(List *L)
{
Node *p,*s;
int coef,expn;
s = L->head = (Node*)malloc(sizeof(Node));//创建头结点
L->head->next = NULL;
while(scanf("%d,%d",&coef,&expn)) {
while(s->next!=NULL && s->next->x.expn >= expn) {
//这个就是找到符合要求结点前驱的循环
s = s->next;
if(s->x.expn==expn) {
s->x.coef += coef;
break;
}
}
//然后就是给它找个空间,把东西放进去,再插入
p = (Node*)malloc(sizeof(Node));
p->x.coef = coef;
p->x.expn = expn;
insert(L,p,s);
}
getchar();//把代表输入结束的那个字符处理掉
}
void addList(List *L1,List *L2,List *L3)
{
Node *p1,*p2,*p3,*tmp;
p3 = L3->head = L1->head;
p1 = L1->head->next;
p2 = L2->head->next;
while(p1&&p2) {
//指数大的进去L3那条表
if(p1->x.expn > p2->x.expn) {
p3->next = p1;
p3 = p1;
p1 = p1->next;
} else if (p1->x.expn < p2->x.expn) {
p3->next = p2;
p3 = p2;
p2 = p2->next;
} else {
//想等的话就系数加起来,当然,还要考虑如果系数相加等于0要怎么办
//加了之后,p2的结点就没有用了,把它free掉吧
p1->x.coef += p2->x.coef;
tmp = p2;
p2 = p2->next;
free(tmp);
if(p1->x.coef < 0.000001) {//因为是浮点数
//相加之后系数为0,那么p1也没用了,更新p1,把它free掉
tmp = p1;
p1 = p1->next;
free(tmp);
}
}
}
p3->next = p1?p1:p2;//把剩下还没插进去的链表都插进去
}
void printList(List *L)
{
Node *p = L->head->next;
while(p) {
printf("%.2fx^%d+",p->x.coef,p->x.expn);
p = p->next;
}
puts("\b ");//先退一下格,在打印个空格上去,把尾部的+处理掉
}