1.一元多项式相加减
(1)建立多项式:存储系数和指数,尾插法创建链表,以系数为0结束,并约定建立的一元多项式链表指数总是按指数从小到大的顺序排列
(2)输出多项式:从第一个元素开始,逐项读出系数和指数,按多项式的形式输出。第一项不带正负号;X的系数为正负1时,只有指数也为1时,输出系数即可,指数不为1时,直接输出指数部分
(3)两个多项式相加:指数相同才加系数,不同时将指数小的排在前面,一个多项式完了之后,将另一个直接接在后面即可
(4)两个多项式相减:将减数的系数变负,然后相加即可
(5)代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct ddd
{
//链表数据域为系数coef和指数expn
int coef;
int expn;
struct ddd *next;
}Polynomial, *Polyn;
Polyn CreatePoly()
{
//尾插法创建多项式链表
Polynomial *head,*rear,*s;
int c,e;
head=(Polynomial *)malloc(sizeof(Polynomial));
rear=head;
scanf("%d,%d",&c,&e);
while(c!=0)
{
s=(Polynomial *)malloc(sizeof(Polynomial));
s->coef=c;
s->expn=e;
rear->next=s;
rear=s;
scanf("%d,%d",&c,&e);
}
rear->next=NULL;
return(head);
}
void PrintPolyn(Polyn P)
{
//多项式输出
Polyn q=P->next;
int flag=1;
if(!q)
{
putchar('0');
printf("\n");
return;
}
while(q)
{
if(q->coef>0&&flag!=1)
putchar('+');//系数大于0并且不是多项式的第一项时,输出"+"
if(q->coef!=1&&q->coef!=-1)
{
//系数不是正负1时,输出系数
printf("%d",q->coef);
if(q->expn==1)
putchar('X');//指数为1,输出X
else if(q->expn)
printf("X^%d",q->expn);//指数不为1,输出X^指数
}
else
{
if(q->coef==1)
{
if(!q->expn)
putchar('1');//系数1,指数0,输出1
else if(q->expn==1)
putchar('X');//系数1,指数1,输出X
else
printf("X^%d",q->expn);
}
if(q->coef==-1)
{
if(!q->expn)
printf("-1");//系数-1,指数0,输出-1
else if(q->expn==1)
printf("-X");//系数1,指数1,输出X
else
printf("-X^%d",q->expn);
}
}
q=q->next;
flag++;
}
printf("\n");
}
Polyn AddPolyn(Polyn pa,Polyn pb)
{
Polyn qa=pa->next;
Polyn qb=pb->next;
Polyn headc,pc,qc;
pc=(Polynomial *)malloc(sizeof(Polynomial));
pc->next=NULL;
headc=pc;
while(qa!=NULL&&qb!=NULL)
{
qc=(Polynomial *)malloc(sizeof(Polynomial));
if(qa->expn<qb->expn)
{
//qa指数小,直接存入qc,qa后移
qc->coef=qa->coef;
qc->expn=qa->expn;
qa=qa->next;
}
else if(qa->expn==qb->expn)
{
//指数相等时,系数相加,存入qc
qc->coef=qa->coef+qb->coef;
qc->expn=qa->expn;
qa=qa->next;
qb=qb->next;
}
else
{
//qb指数小,直接存入qc,qb后移
qc->coef=qb->coef;
qc->expn=qb->expn;
qb=qb->next;
}
if(qc->coef!=0)
{
qc->next=pc->next;
pc->next=qc;
pc=qc;
}
else
free(qc);
}
while(qa!=NULL)
{
//当qa没完时,直接将qa接到qc的后面
qc=(Polynomial *)malloc(sizeof(Polynomial));
qc->coef=qa->coef;
qc->expn=qa->expn;
qa=qa->next;
qc->next=pc->next;
pc->next=qc;
pc=qc;
}
while(qb!=NULL)
{
qc=(Polynomial *)malloc(sizeof(Polynomial));
qc->coef=qb->coef;
qc->expn=qb->expn;
qb=qb->next;
qc->next=pc->next;
pc->next=qc;
pc=qc;
}
return headc;
}
Polyn SubtractPolyn(Polyn pa,Polyn pb)
{
//减法是将减数系数变为-,再相加
Polyn h = pb;
Polyn p = pb->next;
Polyn pd;
while(p)
{
p->coef *= -1;
p = p->next;
}
pd = AddPolyn(pa,h);
for(p = h->next;p;p = p->next)
p->coef *= -1;
return pd;
}
int main()
{
Polyn muil_a,muil_b,muil_c,muil_d;
printf("输入第一组多项式:\n");
muil_a=CreatePoly();
printf("输入第二组多项式:\n");
muil_b=CreatePoly();
printf("两个多项式相加为:\n");
muil_c=AddPolyn(muil_a,muil_b);
PrintPolyn(muil_c);
printf("两个多项式相减为:\n");
muil_d=SubtractPolyn(muil_a,muil_b);
PrintPolyn(muil_d);
return 0;
}
(6)运行结果截图:
2.设有一线性表e=(e1,e2,…,en-1,en),其逆线性表定义为e‘=(en,en-1,…,e2,e1)。请设计一个算法,将线性表逆置,要求逆线性表仍占用原线性表的空间,并且用顺序表和单链表两种方法来表示,写出不同的处理函数。
(1)数组实现逆置:循环一半,交换前后数据
(2)代码:
#include <stdio.h>
#define MAXSIZE 50000
int main()
{
int n,t,i;
printf("输入数据个数:\n");
scanf("%d",&n);
int a[MAXSIZE];
printf("输入数据:\n");
for(i=0;i<n-1;i++)
scanf("%d ",&a[i]);
scanf("%d",&a[n-1]);
for(i=0;i<n/2;i++)
{
t=a[i];
a[i]=a[n-1-i];
a[n-1-i]=t;
}
printf("逆置后数组为:\n");
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
(3)运行结果:
(4)链表实现逆置:用头插法逆置链表
(5)代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node* next;
}LNode,*Linklist;
Linklist CreatFromTail()
{
Linklist L;
LNode *s, *r;
L=(Linklist)malloc(sizeof(LNode));
L->next=NULL;
r=L;
int x;
printf("输入数据(-1结束):\n");
scanf("%d ",&x);
while(x!=-1)
{ s=(Linklist)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return L;
}
void Reverse(Linklist H)
{
LNode *p,*q;
p=H->next;//p指向第一个数据结点
H->next=NULL;//将原链表置为空表H
while(p)
{
q=p;
p=p->next;
q->next=H->next;//将当前结点查到头结点的后面
H->next=q;
}
}
void PrintList(Linklist head)
{
LNode *p,*q;
p=head;
printf("逆置后为:\n");
while(p->next!=NULL)
{
p=p->next;
printf("%d ",p->data);
}
}
int main()
{
Linklist a;
a=CreatFromTail();
Reverse(a);
PrintList(a);
}
(6)运行结果:
3.设指针la和lb分别指向两个无头结点单链表中的首元结点,试设计算法,从表la中删除自第i个元素起共len个元素,并将它们插入表lb的第j个元素之后。
(1)思路:遍历la中的元素,记录下i-1的地址p,然后len-1个数据后,再记录地址q,将这部分数据放到c链表,删除这部分数据p->next = q->next.在lb链表遍历后,找到第j-1个元素,将c链表接到j-1地址后。
(2)代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
}LNode,*Linklist;
void CreatList(Linklist L){
L = (LNode*)malloc(sizeof(LNode));
L = NULL;
}//无头结点
void CreateLinkList(Linklist L,int n){
int i;
Linklist pre,p;
printf("首结点数据:");
L = (LNode*)malloc(sizeof(LNode));
scanf("%d",L->data);
pre = L;
printf("输入剩余%d结点的值\n",n-1);
for(i = 0;i < n - 1;i++){
p = (LNode*)malloc(sizeof(LNode));
scanf("%d",p->data);
pre->next = p;
pre = p;
}
pre->next = NULL;
}
//遍历链表
void show(Linklist L){
Linklist p;
p = L;
while(p){
printf("%5d",p->data);
p = p->next;
}
printf("\n");
}
//求链表长度
int ListLength(Linklist L){
int count;
Linklist p;
count = 0;
p = L;
while(p){
count++;
p = p->next;
}
return count;
}
//删除pa中i开始len元素,将删除元素写到pc中
void Operate(Linklist &pa,Linklist &pc,int i,int len)
{
int j=0,k=0;//j计数至i-1;k计数至len-1
Linklist p,s,l;
p = pa;
while(p->next && j < i - 2){
j++;
p = p->next;
}
s = p;//记住删除前的位置
pc = p->next;
l = pc;
while(k < len - 1){
p = p->next;
l = l->next;
k++;
}
s->next = l->next;//将除了删除的地方连接起来
l->next = NULL;//终点指向空
printf("所要删除的链表元素有:\n");
show(pc);
}
//把pc插入到pb i 元素后
void Operate2(Linklist &pb,Linklist &pc,int i,int len){
int j;
Linklist p,m;
j = 0;
p = pb;
while(p && j < i - 1){
j++;
p = p->next;
}
m = p->next;//记录插入前位置
p->next = pc;//插入pc
while(pc->next){
pc=pc->next;
}
pc->next = m;//连接前面
show(pb);
}
int main(int argc, char *argv[]) {
int m,n,k;
Linklist pa,pb,pc;
CreatList(pa);
CreatList(pb);
CreatList(pc);
CreateLinkList(pa,3);
CreateLinkList(pb,3);
printf("链表a:");
show(pa);
printf("链表b:");
show(pb);
printf("从第几个开始删除");
scanf("%d",&m);
printf("删除多少个");
scanf("%d",&n);
Operate(pa,pc,m,n);
printf("a删除后的元素");
show(pa);
printf("从b的哪里插入");
scanf("%d",&k);
printf("b现在为");
Operate2(pb,pc,k,n);
return 0;
}
(3)运行结果:
4.回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判定给定的字符串是否为回文。
(1)思路:将要待检测的字符串分别放入数组和栈,然后遍历输出比较。因为栈是先进后出,会逆置字符串,和数组输出比较每个字符都相等,则是回文
(2)代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Maxsize 20000
typedef struct PalindromeQueue //定义顺序列表结构体
{
char LinlistQ[Maxsize];
int front ;
int rear ;
};
typedef struct PalindromeStack //定义顺序栈结构体
{
char LinklistS[Maxsize];
int top;
};
void Init(PalindromeQueue *Q,PalindromeStack *S) //初始化
{
Q->front=Q->rear=0;
S->top=-1; //栈空
}
void Operate(PalindromeQueue *Q,PalindromeStack *S)
{
while (S->top != -1 )
{
if(Q->LinlistQ[Q->front] != S->LinklistS[S->top])
{
printf("该字符序列不是回文序列\n");
break;
}
(S->top)--;
(Q->front)++;
}
if (S->top = -1 && Q->front == Q->rear)
{
printf("该序列式是回文序列\n");
}
}
int main()
{
int j=0;
char List[Maxsize];
PalindromeQueue M;
PalindromeStack N;
printf("请输入一段需要判断是否是“回文序列”的字符序列并以'@'字符作为结束标识符\n");
while(1)
{
scanf("%s",List,sizeof(List)); //sizeof时是一个操作符,可测量变量声明后所占内存数
break;
}
Init(&M,&N); //初始化队列和栈
while(List[j] != '@')
{
M.LinlistQ[j]=List[j]; //进入队列
M.rear++; //队尾后移
N.LinklistS[j]=List[j]; //进栈
N.top++;
j++;
}
Operate(&M,&N); //判断是否是回文序列
return 0;
}
(3)运行结果: