期末总结(机考复习)
线性表
反转链表
思路:运用三个指针(head,p,q)完成反转。 head = NULL, p = L, q=L->next;//初始值 p->next =
head, head = p,p = q,q = q->next;//循环部分
这部分代码是刚学时写的,怎么说呢,虽然oj过了,但是过了这么长时间,我自己也看不懂了,并且格式十分的辣眼睛,有时间重写一份思路清晰、格式顺眼的放上来
多项式加减法(无格式控制版)
不需要控制输出格式就简单的多,可用单链表实现,有无头结点均可;也可用数组实现。
单链表版
问题描述:给定两个多项式,求解其和与差。多项式的项数为M,最高幂N(1<=M<=10,1<=N<=1000000)
输入说明:
多项式1:系数值 幂次值(各项按照幂次的降序排列)
多项式2:系数值 幂次值(各项按照幂次的降序排列)
输出说明:
多项式相加结果(各项按照幂次的降序排列)
多项式1-多项式2结果(各项按照幂次的降序排列)
输入样例
4 1 10 2 5 3 4 4 0
4 1 8 -2 5 3 3 4 1
输出样例
6 1 10 1 8 3 4 3 3 4 1 4 0
7 1 10 -1 8 4 5 3 4 -3 3 -4 1 4 0
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
int coef;//存放系数
int expn;//存放幂次
struct LNode *next;
}List, *LinkList;
void Attach(int coef, int expn, LinkList p){//新结点连接至链表
LinkList r;
r=(LinkList)malloc(sizeof(List));
r->coef=coef;
r->expn=expn;
r->next=NULL;
p->next=r;
p=r;
}
LinkList ReadPoly(){
int N,xishu,zhishu;
scanf("%d ",&N);
LinkList head,rear,t;
head = (LinkList)malloc(sizeof(List));
head->next =NULL;
rear = head;
while(N--){
scanf("%d %d",&xishu,&zhishu);
Attach(xishu,zhishu,rear);
rear = rear->next;
}
return head;
}
int compare(int a, int b){
if(a>b) return 1;
else if(a == b) return 0;
else return -1;
}
LinkList Polynomeplus(LinkList head1, LinkList head2){
LinkList current1,current2,temp,s,L,rear;//遍历两个链表+创造一个有头结点的新的链表
int index=0,j;
current1=head1->next;
current2=head2->next;
L = (LinkList)malloc(sizeof(List));
L->next = NULL;//新链表头结点
rear = L;//插入结点指针指向头结点
while(current1 && current2){
switch (compare(current1->expn,current2->expn))//什么时候用到free(temp)?
{
case 1://第一个链表当前项指数大,将当前结点赋给新结点,然后将结点连接到链表
Attach(current1->coef, current1->expn,rear);
current1=current1->next;//指针下移
rear=rear->next;
break;
case 0://两个链表当前项指数相同,系数相加
j=current1->coef+current2->coef;
if(!j){//系数和为0后该项不存入链表,遍历指针下移
current1=current1->next;
current2=current2->next;
}
else {//系数和不为0
Attach(j,current1->expn,rear);
current1=current1->next;
current2=current2->next;
rear=rear->next;
}
break;
case -1://第二个链表当前项指数大
Attach(current2->coef,current2->expn,rear);
current2=current2->next;
rear=rear->next;
break;
}
}
//表1没结束,表2结束,将表1剩余结点赋给新结点后连入
while(current1){ //为什么(current1 && !current2)不行??
Attach(current1->coef,current1->expn,rear);
current1=current1->next;//指针下移
rear=rear->next;
}
//表2没结束,表1结束,将表2剩余结点赋给新结点后连入
while(current2){
Attach(current2->coef,current2->expn,rear);
current2=current2->next;
rear=rear->next;
}
//改变头结点中存的项数
s=L;
while(s->next){s=s->next;++index;}//退出时s指向最后一个结点
L->expn=index;
return L;
}
LinkList PolynomeSubstruct(LinkList head1, LinkList head2){
LinkList p,turn;
turn=head2->next;
while (turn)
{
turn->coef=-(turn->coef);
turn=turn->next;
}
p=Polynomeplus(head1,head2);
return p;
}
void Display(LinkList head){ //遍历+打印函数
LinkList p;
printf("%d ",head->expn);
p=head->next;
while(p){
printf("%d %d ",p->coef,p->expn);
p=p->next;
}
}
int main(){
LinkList Head1,Head2,H1,H2;
Head1 = ReadPoly();//√链表创建成功
Head2 = ReadPoly();
H1=Polynomeplus(Head1,Head2);
Display(H1);
printf("\n");
H2=PolynomeSubstruct(Head1,Head2);
Display(H2);
return 0;
}
多项式加减法在多个题目中都有出现,其主体结构是3个while
写这道题的时候还没有碰到二级指针的问题,所以有一个attach函数来增加结点。也可以用二级指针来解决,这样就需要attach函数了,直接就可对表进行修改,但是每次都要遍历来找尾指针,时间复杂度可能会上升,对单链表结构体进行改进,增加一个尾指针始终指向单链表尾结点即可。
约瑟夫环(循环单链表)
题目变形即数组部分的报数出列问题,约瑟夫环也可用数组解决,方便快捷。
涉及循环单链表的建立,本题中用的方法是先建有头结点的单链表,然后去掉头结点
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{ //定义结点类型
int number;
int mcode;
struct LNode *next;
}List,*LinkList;
LinkList CreatLinkList(int length){
LinkList head,p,pre;
int i;
head=(LinkList)malloc(sizeof(List));
head->next=head;
pre=head;
for(i=1;i<=length;i++){
p=(LinkList)malloc(sizeof(List));
p->number=i;
scanf("%d", &p->mcode);
pre->next=p;
p->next=head;
pre=p;
}
head=head->next;//去掉头结点
free(pre->next);
pre->next=head;
return head;//head已经指向第一个结点且为循环单链表
}
void Joseph(LinkList head,int m){
LinkList p,d,prev,s;
p=head;
s=head;
while(s->next!=head){s=s->next;}
prev=s;
int i;
while(p->next!=p){
for(i=1;i<m;i++){
p=p->next;
prev=prev->next;
}
printf("%d ",p->number);
m=p->mcode;
d=p;
p=p->next;
prev->next=p;
free(d);
}
printf("%d ",p->number);
free(p);
}
int main(){
int length,password;
LinkList H;
scanf("%d %d\n",&length,&password);
H=CreatLinkList(length);
Joseph(H,password);
return 0;
}
学生信息管理
根据退学学生的学号,将其信息从链表中删除。学生数据只保存姓名、学号、性别。
输入说明:
n个学生数据,1<=n<=10 姓名不超过20个字符,学号整型,性别字符型,输入以#结束
退学学生学号
输出说明:
有退学学生,输出删除该学生后的学生数据
无退学学生,输出错误信息No
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
char name[20];
int number;
char sex;
struct LNode *next;
}List, *LinkList;
LinkList ReadInformation();//读入学生信息
void DeleteLNode(LinkList head,int number);//查找退学学生并删除删除该指针指向的结点
void Display(LinkList head);//输出数据
int main(void){
LinkList head;
head = ReadInformation();
int number;
scanf("%d\n",&number);
DeleteLNode(head,number);
return 0;
}
LinkList ReadInformation(){//#的ASCII码是23 头结点没有数据
LinkList head,p,s;
head = (LinkList)malloc(sizeof(List));
head->next = NULL;
p = head;
s = (LinkList)malloc(sizeof(List));
scanf("%s ",s->name);
while((s->name[0])!='#'){//!!!!关于以#结尾数据的处理
scanf("%d %c",&s->number,&s->sex);
p->next=s;
p=s;
s=p->next;
s=(LinkList)malloc(sizeof(List));
scanf("%s ",s->name);
}
p->next=NULL;
return head;
}
void DeleteLNode(LinkList head, int number){
LinkList s,r;
s = head->next;
r = head;
while (s && s->number!=number){
r = s;
s = s->next;
}
if(s){
r->next = s->next;
free(s);
Display(head);
}
else{
printf("No\n");
}
}
void Display(LinkList head){
LinkList p;
p = head->next;
while(p){
printf("%s %d %c\n",p->name,p->number,p->sex);
p = p->next;
}
}
难点是对#输入的处理
一元稀疏多项式计算器(含格式控制)
结构体+数组版
问题描述:
n,m,t 第一个多项式的项数 第二个多项式的项数 运算类型0加1减
2n个整数 系数指数
2m个指数 指数系数
指数递增形式给出
输出:
按指数从低到高的顺序在以多项式输出,系数为负数时输出减号,系数为0不出现,指数为1不输出指数
输入样例
6 2 0
1 0 1 1 1 2 1 3 1 4 1 5
-1 3 -1 4
输出样例
1+x+x^2+ x^5
注:此题测试案例过3/4
#include <stdio.h>
typedef struct {
int coef;
int expn;
}poly;
int main (void) {
int n, m, t, i, j, flag = 0, count;
scanf ("%d %d %d", &n, &m, &t);
int pos = n;//指向第一个多项式末尾
poly p1[100], p2[100], tmp;
for (i = 0; i < n; i++) {
scanf ("%d %d", &p1[i].coef, &p1[i].expn);
}
for (i = 0; i < m; i++) {
scanf ("%d %d", &p2[i].coef, &p2[i].expn);
}
if (!t) {
for (i = 0; i < m; i++) {
flag = 0;
for (j = 0; j < n; j++) {
if (p2[i].expn == p1[j].expn) {
flag = 1;
break;
}
}
if (flag) {
p1[j].coef += p2[i].coef;
}
else {
p1[pos++] = p2[i];
}
}
}
else {
for (i = 0; i < m; i++) {
flag = 0;
for (j = 0; j < n; j++) {
if (p2[i].expn == p1[j].expn) {
flag = 1;
break;
}
}
if (flag) {
p1[j].coef -= p2[i].coef;
}
else {
p1[pos].coef = -p2[i].coef;
p1[pos].expn = p2[i].expn;
pos++;
}
}
}
/*指数排序*/
for (i = 0; i < pos; i++) {
for (j = 0; j < pos -i - 1; j++) {
if (p1[j].expn > p1[j + 1].expn) {
tmp = p1[j];
p1[j] = p1[j + 1];
p1[j + 1] = tmp;
}
}
}
/*输出格式控制*/
count = 1;
for (i = 0; i < pos; i++) {
if (p1[i].coef > 0 && count !=1) {
printf ("+");
}
if (p1[i].coef) {
if (p1[i].coef == 1) {
if (p1[i].expn == 0) {
printf ("1");
}
else if (p1[i].expn == 1) {
printf ("x");
}
else {
printf ("x^%d", p1[i].expn);
}
}
else if (p1[i].coef == -1) {
if (p1[i].expn == 0) {
printf ("-1");
}
else if (p1[i].expn == 1) {
printf ("-x");
}
else {
printf ("-x^%d", p1[i].expn);
}
}
else {
printf ("%dx^%d", p1[i].coef, p1[i].expn);
}
}
count++;
}
return 0;
}
思想是先将同类项合并(指数相同的项),不相同的项添加到数组末尾,然后根据指数排序,再根据格式要求来输出(系数为0,指数为1…)。难点是格式控制
缺点是只能进行一次运算,运算过后源数据发生改变。
单链表版
输入样例
6 3 0
1 0 1 1 -3 2 1 3 1 4 1 5
-1 3 -2 4 1 5
输出样例
1+x-3x^2 - x ^ 4 + 2x ^5
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode{
int coef;
int expn;
struct LNode *next;
}List, *LinkList;
void Attach(int coef, int expn, LinkList p){//新结点连接至链表
LinkList r;
r=(LinkList)malloc(sizeof(List));
r->coef=coef;
r->expn=expn;
r->next=NULL;
p->next=r;
p=r;
}
LinkList ReadPoly(int n){
int xishu,zhishu;
LinkList head,rear;
head = (LinkList)malloc(sizeof(List));
head->next =NULL;
rear = head;
while(n--){
scanf("%d %d",&xishu,&zhishu);
Attach(xishu,zhishu,rear);
rear = rear->next;
}
return head;
}
int compare(int a, int b){
if(a<b) return 1;
else if(a == b) return 0;
else return -1;
}
LinkList Polynomeplus(LinkList head1, LinkList head2){
LinkList current1,current2,temp,L,rear;//遍历两个链表+创造一个有头结点的新的链表
int j;
current1=head1->next;
current2=head2->next;
L = (LinkList)malloc(sizeof(List));
L->next = NULL;//新链表头结点
rear = L;//插入结点指针指向头结点
while(current1 && current2){
switch (compare(current1->expn,current2->expn))//什么时候用到free(temp)?
{
case 1://第一个链表当前项指数小,将当前结点赋给新结点,然后将结点连接到链表
Attach(current1->coef, current1->expn,rear);
current1=current1->next;//指针下移
rear=rear->next;
break;
case 0://两个链表当前项指数相同,系数相加
j=current1->coef+current2->coef;
if(!j){//系数和为0后该项不存入链表,遍历指针下移
current1=current1->next;
current2=current2->next;
}
else {//系数和不为0
Attach(j,current1->expn,rear);
current1=current1->next;
current2=current2->next;
rear=rear->next;
}
break;
case -1://第二个链表当前项指数小
Attach(current2->coef,current2->expn,rear);
current2=current2->next;
rear=rear->next;
break;
}
}
//表1没结束,表2结束,将表1剩余结点赋给新结点后连入
while(current1){
Attach(current1->coef,current1->expn,rear);
current1=current1->next;//指针下移
rear=rear->next;
}
//表2没结束,表1结束,将表2剩余结点赋给新结点后连入
while(current2){
Attach(current2->coef,current2->expn,rear);
current2=current2->next;
rear=rear->next;
}
return L;
}
LinkList PolynomeSubstruct(LinkList head1, LinkList head2){
LinkList p,turn;
turn=head2->next;
while (turn)
{
turn->coef=0-(turn->coef);
turn=turn->next;
}
p=Polynomeplus(head1,head2);
return p;
}
LinkList Function(int t, LinkList head1, LinkList head2){
LinkList P;
switch (t)
{
case 0:
P=Polynomeplus(head1, head2);
break;
case 1:
P=PolynomeSubstruct(head1, head2);
break;
}
return P;
}
void Display(LinkList head){
int flag = 1;
LinkList q;
q = head->next;
if(!q){printf("0\n");return;}
if(q->coef == 0){q = q->next;}//易忽略的地方就是链表1为0,链表2不为0的减法,不能输出0
while (q){ //若一元多项式为真,执行while循环
if (q->coef > 0 && flag != 1)
putchar('+'); //如果一元多项式的系数大于0并且flag已经不再是1,则输出+
if (q->coef != 1 && q->coef != -1){ //如果一元多项式系数不是1也不是-1
printf("%d", q->coef); //直接输出一元多项式的系数
if (q->expn == 1) //再看指数,如果指数是1,直接输出x
putchar('x');
else if (q->expn)
printf("x^%d", q->expn); //否则 输出X^%d
}
else {
if (q->coef == 1) { //如果一元多项式的系数是1
if (!q->expn) //在判断指数是否为真,若指数为0,直接输出1即可
putchar('1');
else if (q->expn == 1)
putchar('x'); //如果再系数是1的情况下指数也是1,则直接输出x即可
else
printf("x^%d", q->expn);// 系数为1,指数不为1,则输出X^%d
}
if (q->coef == -1) { //如果系数为-1
if (!q->expn)
printf("-1"); //若指数为0,则输出-1
else if (q->expn == 1)
printf("-x"); //若指数为1,则输出-x
else
printf("-x^%d", q->expn);
}
}
q = q->next; //使当前指针指向链表的下一个结点。
flag++;
}
printf("\n");
}
int main(){
int n,m,t;
scanf("%d %d %d\n", &n, &m, &t);//√输入正确
LinkList head1,head2,H,p;
head1 = ReadPoly(n);//√链表创建成功
head2 = ReadPoly(m);//√链表创建成功
H=Function(t,head1, head2);
Display(H);
return 0;
}
格式控制
链表去重
(见数组部分题目)
有序表的合并去重
两个有序表L1和L2,数据元素为单调增的正整数,内部无重复元素,L2合并到L1中,仍为单调增,无重复元素
正整数均小于10000
输入样例
6 7
1 2 5 6 10 13
1 3 5 8 19 22 31
输出样例
1 2 3 5 6 8 10 13 19 22 31
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int elem;
struct node *next;
}node;
void InitList(node *L);
void CreatList(node *L,int n);
void Insert(node *L,int e,node *tail);
void DisPlay(node *L);
int main(void){
int l1,l2;
scanf("%d %d\n",&l1,&l2);
node L1,L2,L3;
InitList(&L1);
InitList(&L2);
InitList(&L3);
CreatList(&L1,l1);
CreatList(&L2,l2);
node *current1,*current2,*rear;
current1 = L1.next;
current2 = L2.next;
rear = &L3;
while(current1&¤t2){
//两张表均不为空
int k=0;
if(current1->elem > current2->elem){
k = current2->elem;
Insert(&L3,k,rear);
current2 = current2->next;
rear = rear->next;
}
else if(current1->elem < current2->elem){
k = current1->elem;
Insert(&L3,k,rear);
current1 = current1->next;
rear = rear->next;
}
else if(current1->elem == current2->elem){
k = current1->elem;
Insert(&L3,k,rear);
current1 = current1->next;
current2 = current2->next;
rear = rear->next;
}
}
while(current1){
int k=0;
k = current1->elem;
Insert(&L3,k,rear);
current1 = current1->next;
rear = rear->next;
}
while(current2){
int k =0;
k = current2->elem;
Insert(&L3,k,rear);
current2 = current2->next;
rear = rear->next;
}
/*DisPlay(&L1);
DisPlay(&L2);*/
DisPlay(&L3);
return 0;
}
void InitList(node *L){
L = (node*)malloc(sizeof(node));
L->next = NULL;
L->elem = 0;
}
void CreatList(node *L,int n){
int i,t;
node *p;
p = (node*)malloc(sizeof(node));
scanf("%d",&t);
p->elem = t;
p->next = NULL;
L->next = p;
for(i=1;i<n;i++){
node *s;
int m;
s = (node*)malloc(sizeof(node));
scanf("%d",&m);
s->elem = m;
s->next = NULL;
p->next = s;
p = s;
}
}
void Insert(node *L,int e,node *tail){
node *p,*s;
p = (node*)malloc(sizeof(node));
p->elem = e;
p->next = NULL;
tail->next = p;
tail = p;
}
void DisPlay(node *L){
node *p;
p = L->next;
while(p){
printf("%d ",p->elem);
p = p->next;
}
printf("\n");
}
栈和队列
队列中的元素排序
问题描述:
给定一个队列,请用一系列合法的队列操作函数,比如判断队列是否为空,入队,出队,将队列中的元素从小到大排序
第一个数据为项数
输入:10 3 6 4 8 7 2 9 0 1 5
输出:0 1 2 3 4 5 6 7 8 9
思路:利用循环队列实现,比用指针方便。当然,STL最方便。先将min设为一个很大数字,对输入的序列做一轮循环,找到最小的值输出,然后同样的方法找次小的数字,然后输出,结束条件是队列为空。每一轮循环中,将数字出列与min进行判断,大就再入列,小的替换min,被替换掉的数字再入列。第一次循环是m次,第二次循环则是m-1次,注意这个两层循环中的关系for(j=0;j<m;j++){ for(k=j;k<m;k++)...
。
#include<stdio.h>
#include<stdlib.h>
#define INF 999999999
#define maxsize 999//正整数N<1000
typedef struct {//定义结构体队列Queue,队列为顺序队列
int data[maxsize];
int front;
int rear;
}Queue;
void InitQueue(Queue *head){//队列初始化,head是Queue型的指针
head->front = head->rear = 0;
}
int IsEmpty(Queue *head){
if(head->front == head->rear) return 1;//循环条件下判断队空
else return 0;
}
void InsertQueue(Queue *head,int data){//插入元素尾指针动
if(head->front == (head->rear+1)%maxsize) return;
head->rear = (head->rear +1)%maxsize;//队尾指针+1
head->data[head->rear] = data;//赋值
}
int DeleteQueue(Queue *head){//删除元素头指针动,返回删除元素
if(head->rear == head->front) return 0;
head->front = (head->front +1)%maxsize;
return head->data[head->front];
}
int main(void){
Queue q,temp;
InitQueue(&q);
InitQueue(&temp);
int m,n,i,j,k,min;//项数
scanf("%d", &m);
for(i=0;i<m;i++){
scanf(" %d",&n);//把格式控制的空格放在前面
InsertQueue(&q,n);
}
for(j=0;j<m;j++){
min = INF;//寻找最小值的方法,要牢记
for(k=j;k<m;k++){
n = DeleteQueue(&q);
if(n<min){
if(min != INF) InsertQueue(&q,min);
min = n;
}
else{
InsertQueue(&q,n);
}
}
InsertQueue(&temp,min);
}
printf("%d ",DeleteQueue(&temp));
while(!IsEmpty(&temp)){
printf("%d ",DeleteQueue(&temp));
}
printf("\n");
return 0;
}
判断栈输出顺序正确与否
输入说明:
栈的最大容量M 压栈数据长度N 要验证的弹栈序列个数K
压栈数据
K行数据 每行是需要验证的弹栈序列
输出说明:
序列可能发生输出YES,不可能输出NO
#include<stdio.h>
#include<stdlib.h>
typedef struct {
int data[1000];
int top;
}Stack;
Stack* tops;
Stack* InitStack(Stack* s){
s->top = -1;
return s;
}
Stack* Push(Stack* tops, int e){
tops->top++;
tops->data[tops->top] = e;
return tops;
}
int Pop(Stack* top){
int ret;
if (tops->top == -1) return 0;
else
{
ret = tops->data[tops->top];
tops->top--;
return ret;
}
}//删除并返回栈顶元素
int Judge(Stack * tops, int n, int y[], int m, int s[]){
int i = 0, j = 0;
InitStack(tops);//置空栈
tops = Push(tops, s[i]);//将第一个元素入栈,tops为栈顶元素
while (tops->top < m && j < n){
if (tops->data[tops->top] == y[j] && tops->top != -1)
{
Pop(tops);
j++;
}
else
{
i++;
tops = Push(tops, s[i]);
}
}
if (tops->top == -1) return 1;
else return 0;
}
int main(){
tops = (Stack*)malloc(sizeof(Stack));
int m, n, k, i, j, y[1000], s[1000], h[10000];
scanf("%d %d %d", &m, &n, &k);
for (i = 0; i < n; i++) scanf("%d", &s[i]);
for (i = 0; i < k; i++){
for (j = 0; j < n; j++){
scanf("%d", &y[j]);
}
h[i] = Judge(tops, n, y, m, s);
}
for (i = 0; i < k; i++){
if (h[i] == 1) printf("YES");
else printf("NO");
if (i != k - 1) printf("\n");
}
return 0;
}
每行数据由两行构成,第一行只有一个整数n,表示序列长度,同时表示栈的输入序列为1,2,…,n
第2行为n个整数,表示需要判断的出栈序列
输出一个yes或no
输入样例
6
3 4 2 1 5 6
输出样例
yes
#include<stdio.h>
#define MAXSIZE 20
#define ElemType int
#define Status int
#define ok 1
#define error 0
#define overflow -1
typedef struct {
ElemType data[MAXSIZE];
int top;
}stack;
void InitStack (stack *S);
Status Push (stack *S, ElemType e);
Status Pop (stack *S, ElemType *x);
int EmptyStack (stack *S);
int FullStack (stack *S);
Status GetTopStack (stack *S, ElemType *x);
void Display (stack S);
int main (void) {
stack S, C;
InitStack (&S);
int n;
scanf ("%d", &n);
int i, j, e, x, p1 = 1, p2 = 1;
int check[n + 1],num[n + 1];
for (i = 1; i <= n; i++) {
scanf ("%d",&check[i]);
num[i] = i;
}
//Display(S);
while (p2 <= n ) {
if (num[p1] == check[p2]) {
p1++;
p2++;
}
else if (!EmptyStack (&S)) {
GetTopStack (&S,&x);
if (x == check[p2]) {
p2++;
Pop (&S, &x);
}
}
else if (p1 <= n) {
Push (&S, num[p1]);
p1++;
}
else break;
}
if (EmptyStack (&S)) printf ("yes\n");
else printf ("no\n");
return 0;
}
void InitStack (stack *S) {
S->top = -1;
}
Status Push (stack *S, ElemType e) {
if (FullStack (S)) return error;
S->data[++S->top] = e;
return ok;
}
Status Pop (stack *S, ElemType *x) {
if (EmptyStack (S)) return error;
*x = S->data[S->top];
S->top--;
return ok;
}
int EmptyStack (stack *S) {
if (S->top == -1) return 1;
return 0;
}
int FullStack (stack *S) {
if (S->top == MAXSIZE -1) return 1;
return 0;
}
Status GetTopStack (stack *S, ElemType *x) {
if (EmptyStack (S)) return error;
*x = S->data[S->top];
return ok;
}
void Display (stack S) {
if (FullStack (&S)) printf ("full\n");
else {
while (S.top != -1){
printf ("%d",S.data[S.top]);
S.top--;
}
}
printf ("\n");
}
难点是判断函数,如何根据栈空判断
括号配对问题
输出样例
No
No
Yes
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxsize 9999
typedef struct{//char从0开始,0~127,top=-1栈为空
char data[maxsize];//存储下标为0~maxsize-1
int top;
}Stack;
void InitStack(Stack *S){
S->top = -1;
}
int IsEmpty(Stack *S){
if(S->top == -1) return 1;
else return 0;
}
int Push(Stack *S, char x){
if(S->top == maxsize-1) return 0;
S->top++;
S->data[S->top] = x;//指针先上移再赋值
return 0;
}
int GetTop(Stack *S,char *x){
if(S->top == -1) return 0;
else{
*x = S->data[S->top];
return 1;
}
}
int Pop(Stack *S, char *x){
if(S->top == -1) return 0;
else{
*x = S->data[S->top];
S->top--;
return 0;
}
}
int Match(char a, char b){
if(a+1 == b||a+2 == b)return 1;//利用ASCII码
else return 0;
}
int match(char *str){
Stack S;
int i;
char a;
InitStack(&S);
for(i=0;str[i]!='\0';i++){
switch(str[i]){
case '(':
case '{':
case '[':
Push(&S, str[i]);
break;
case ')':
case ']':
case '}':
if(IsEmpty(&S)){//栈空
printf("No\n");
return 0;
}
else{
GetTop(&S,&a);
if(Match(a,str[i])) Pop(&S,&a);
else{
printf("No\n");
return 0;
}
}
}
}
if(IsEmpty(&S)) printf("Yes\n");
else printf("No\n");
return 0;
}
int main(void){
int n;
char a[9999];
scanf("%d",&n);
while(n--){
scanf("%s",a);
match(a);
}
return 0;
}
假设一个表达式或一段程序中含有三种括号(),[],{}
判读给定的表达式或程序中所含括号是否正确配对出现
每行为一个含有括号的表达式或一段程序
输出wrong或right
输入样例
while(m<(a[8]+t){m=m+1;t=t-1;}
输出样例
wrong
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Status int
#define ok 1
#define error 0
#define MAXSIZE 50
typedef struct{
char data[MAXSIZE];
int top;
}stack;
void InitStack(stack *S);
Status Push(stack *S,char e);
Status GetTopStack(stack *S,char *x);
Status Pop(stack *S, char *x);
int EmptyStack(stack *S);
int match(char x,char y);
int Match(char s[]);
void Clear(stack *S);
int main(void){
char str[MAXSIZE];
gets(str);
Match(str);
return 0;
}
void InitStack(stack *S){
S->top=-1;
}
Status Push(stack *S,char e){
if(S->top==MAXSIZE-1)return error;
S->data[++S->top] = e;
return ok;
}
Status GetTopStack(stack *S,char *x){
if(EmptyStack(S)==1)return error;
*x = S->data[S->top];
return ok;
}
Status Pop(stack *S, char *x){
if(EmptyStack(S)==1)return error;
*x = S->data[S->top];
S->top--;
return ok;
}
int EmptyStack(stack *S){
if(S->top==-1) return 1;
else return 0;
}
int match(char x,char y){
if(x+1==y||x+2==y) return 1;
else return 0;
}
void Clear(stack *S){
S->top = -1;
}
int Match(char s[]){
stack S;
int i;
char a;
InitStack(&S);
for(i=0;s[i]!='\0';i++){
switch(s[i]){
case '(':
case '{':
case '[':
Push(&S, s[i]);
break;
case ')':
case ']':
case '}':
if(EmptyStack(&S)){//栈空
printf("wrong\n");
return 0;
}
else{
GetTopStack(&S,&a);
if(match(a,s[i])) Pop(&S,&a);
else{
printf("wrong\n");
return 0;
}
}
}
}
if(EmptyStack(&S)) printf("right\n");
else printf("wrong\n");
return 0;
}
报数出列
(见数组部分)
后缀表达式求值
每个操作数的取值范围为0~9,运算符+-/四种
表达式长度不超过100 均没有错误
输出表达式的值
栈:操作数入栈,操作符连续两次出栈
输入样例
45+23-
输出样例
15
#include<stdio.h>
#include<string.h>
#define MAXSIZE 100
#define Status int
#define ok 1
#define error 0
typedef struct{
int data[MAXSIZE];
int top;
}stack;
void InitStack(stack *S);
Status Push(stack *S, int e);
Status Pop(stack *S, int *x);
int main(void){
char str[MAXSIZE];
gets(str);
stack S;
InitStack(&S);
int i,ans;
for( i = 0; i < strlen(str); i++){
int a,b;
ans = 0;
if( str[i] >='0' && str[i] <= '9'){
Push(&S,str[i]-'0');
}
if( str[i] == '+'){
Pop(&S,&a);
Pop(&S,&b);
ans = b + a;
Push(&S,ans);
}
if( str[i] == '-'){
Pop(&S,&a);
Pop(&S,&b);
ans = b - a;
Push(&S,ans);
}
if( str[i] == '*'){
Pop(&S,&a);
Pop(&S,&b);
ans = b * a;
Push(&S,ans);
}
if( str[i] == '/'){
Pop(&S,&a);
Pop(&S,&b);
ans = b / a;
Push(&S,ans);
}
}
int value;
Pop(&S,&value);
printf("%d\n",value);
/*for(i=0;i<strlen(str);i++){
printf("%d ",str[i]);
}*/
return 0;
}
void InitStack(stack *S){
S->top = -1;
}
Status Push(stack *S, int e){
if(S->top == MAXSIZE-1) return error;
S->data[++S->top] = e;
return ok;
}
Status Pop(stack *S, int *x){
if(S->top == -1) return error;
*x = S->data[S->top];
S->top--;
return ok;
}
前缀表达式求值
操作数为整数,运算符只包含+ * - /预算结果为整数
输入一行前缀表达式,如+ * + 42 8 - 36 6 / 9 3,表达式长度不超过100
输出表达式的值
输入样例
➕ ✖ ➕ 42 8 - 36 6 / 9 3
输出样例
1503
#include<stdio.h>
#include<string.h>
#define MAXSIZE 101
#define Status int
#define ok 1
#define error 0
/*顺序栈*/
typedef struct{
int data[MAXSIZE];
int top;
}stack;
void InitStack(stack *S);
Status Push(stack *S, int e);
Status Pop(stack *S, int *e);
Status GetTopStack(stack *S,int *e);
int EmptyStack(stack *S);
int StackLen(stack *S);
int main(void){
char str[MAXSIZE],op[MAXSIZE];
gets(str);//字符串含空格 且两位数为两个字符,并不是用于计算的两位数
stack S;
InitStack(&S);
int i,j,ans=0,count=0,k;
for( i = strlen(str) - 1; i >= 0; i--){
int a,b;
//处理多位数
ans = 0;
if( str[i] >= '0' && str[i] <= '9'){
count++;
if( str[i-1] ==' '){
for( j = i ; j < i + count ; j++){
ans = ans * 10 + str[j] - '0';
}
Push(&S,ans);
count = 0;
ans = 0;
}
}
if( str[i] == '+' ){
Pop(&S,&a);
Pop(&S,&b);
ans = a + b;
Push(&S,ans);
ans = 0;
}
if( str[i] == '-' ){
Pop(&S,&a);
Pop(&S,&b);
ans = a - b;
Push(&S,ans);
ans = 0;
}
if( str[i] == '*' ){
Pop(&S,&a);
Pop(&S,&b);
ans = a * b;
Push(&S,ans);
ans = 0;
}
if( str[i] == '/' ){
Pop(&S,&a);
Pop(&S,&b);
ans = a / b;
Push(&S,ans);
ans = 0;
}
}
int value;
Pop(&S,&value);
printf("%d\n",value);
//printf("%d\n",strlen(str)); 23
return 0;
}
void InitStack(stack *S){
S->top = -1;
}
Status Push(stack *S, int e){
if(S->top==MAXSIZE-1) return error;
S->data[++S->top] = e;
return ok;
}
Status Pop(stack *S, int *e){
if(EmptyStack(S)==1) return error;
*e = S->data[S->top];
S->top--;
return ok;
}
Status GetTopStack(stack *S,int *e){
if(EmptyStack(S)==1) return error;
*e = S->data[S->top];
return ok;
}
int EmptyStack(stack *S){
if(S->top==-1) return 1;
else return 0;
}
int StackLen(stack *S){
return S->top+1 ;
}
数组、串和矩阵
链表去重
给定键值为整数的单链表,将键值的绝对值有重复的结点删除,只有键值或其绝对值等于k的第一个结点备保留在L中
第一行
链表第一个结点的地址和结点个数(1<=n<=100)。地址是非负的5位整数,NULL=-1
随后n行,每行3个整数
address key next
输出
第一行为去重后的链表长度
每个结点占一行 按address key next格式输出
测试样例
00100 5
99999 7 87654
23854 -15 00000
87654 -15 -1
00000 15 99999
00100 21 23854
输出样例
3
00100 21 23854
23854 -15 99999
99999 7 -1
#include<stdio.h>
#include<math.h>
#define MAXSIZE 100000
typedef struct node{
int key;
int next;
}node;
/*全局变量防爆栈*/
node s[MAXSIZE];
int visit[MAXSIZE] = {0},right[MAXSIZE],del[MAXSIZE],s1[MAXSIZE];
int main(void){
int n,first_address;
scanf ("%d %d",&first_address,&n);
int i, j = 0, num = 0;
//将结点按地址的数值存入数组中
for (i = 0; i < n; i++) {
int address, key, next;
scanf ("%d %d %d",&address,&key,&next);
s[address].key = key;
s[address].next = next;
}
//按next指针将元素提出来组成一个新的数组,建立一个下标为顺序,值为地址的数组s1[maxsize]
while (first_address!=-1) {
s1[j++] = first_address;
first_address = s[first_address].next;
num++;
}
int cnt1 = 0,cnt2 = 0,k;
for (i = 0; i < num; i++) {
k = s[s1[i]].key;
if (visit[(int)fabs(k)]) {
del[cnt2++] = s1[i];
}
else {
right[cnt1++] = s1[i];
visit[(int)fabs(k)] = 1;
}
}
//输出right
printf ("%d\n",cnt1);
for (i = 0; i < cnt1; i++) {
printf ("%05d %d", right[i], s[right[i]].key);
if(i != cnt1-1){
printf (" %05d\n", right[i+1]);
}
else{
printf (" -1\n");
}
}
return 0;
}
找位置
对给定字符串,找出有重复的字符,并给出其位置
输入一个由字母和数字组成的字符串,长度不超过100
下标从0开始,相同的字母在一行表示出其出现过的位置
样例输入
abcaaAB12ab12
样例输出
a:0,a:3,a:4,a:9
b:1,b:10
1:7,1:11
2:8,2:12
#include<stdio.h>
#include<string.h>
#define MAXSIZE 101
void fun (char *p);
int main (void) {
char str[MAXSIZE];
scanf ("%s", str);
fun (str);
return 0;
}
void fun (char *p) {
int i, j, k, len, flag, count, past;
int pos[MAXSIZE];
len = strlen (p);
for (i = 0; i < len; i++) {
flag = 0;//是否出现过重复字符
count = 0;//有多少个重复字符
past =0;//之前出现过,为1
for (k = 0; k <= i - 1; k++) {
if (*(p + k) == *(p + i)) {
past = 1;
}
}
for (j = i + 1; j < len; j++) {
if (*(p + j) == *(p + i) && past == 0) {
flag = 1;
pos[count++] = j;
}
}
if (flag) {
printf ("%c:%d",*(p + i), i);
for (j = 0; j < count; j++) {
//if (j != count -1) printf (",");
printf (",%c:%d", *(p + pos[j]), pos[j]);
}
printf ("\n");
}
}
}
分组统计
样例数m
个数n
第一行:n个数
第二行:上面n个数对应的分组
按号从小到大输出,组内数字也按编号从小到大输出
n不超过100,数和分组号的值都不超过10000
样例输入
1
7
3 2 3 8 8 2 3
1 2 3 2 1 3 1
样例输出
1={2=0,3=2,8=1} 第一组中2出现了0次,3出现了2次,8出现了1次
2={2=1,3=0,8=1}
3={2=1,3=1,8=0}
#include<stdio.h>
int data[10010][10010] = {0}, num[110];
int main (void) {
int m, n, i, j, count, tmp, temp, flag;
scanf ("%d", &m);
if (m == 0) return 0;
while (m--) {
scanf ("%d", &n);
for (i = 0; i < n; i++) {
scanf ("%d", &num[i]);
data[0][num[i]] = 1;
}
//count = 0;
for (i = 0; i < n; i++) {
scanf ("%d", &tmp);
data[tmp][num[i]]++;
if (data[tmp][0] == 0) data[tmp][0] = 1;
}
for (i = 0; i < 10010; i++) {
if (data[i][0]) {
printf ("%d={",i);
flag = 0;
for (j = 1; j < 10010; j++) {
if (data[0][j]) {
if (flag) printf(",");
else flag = 1;
printf("%d=%d", j, data[i][j]);
}
}
printf("}\n");
}
}
//置零
for (i = 0; i < 10010; i++) {
for (j = 0; j < 10010; j++) {
data[i][j] = 0;
}
}
}
return 0;
}
报数出列
已知N个人(以编号1,2,3,…,N分别表示)排成一列,
第一轮从编号为1的人开始依次报数,数到2的倍数的人出列;
第二轮从头开始依次报数,数到3的倍数的人出列;
第三轮再次从头开始依次报数,数到2的倍数的人出列;
第四轮从头开始依次报数,数到3的倍数的人出列;
依此规律重复下去,直到队列中的人数不超过三个为止。
要求输出此时队列中剩下的人在初始队列中的编号。
问题输入
一个正整数N,表示初始人数,N≤5000。
问题输出
输出队列中剩下的人在初始队列中的编号,编号之间有一个空格。
输入样例
20
输出样例
1 7 19
链表实现队列
剩一个测试点未通过
#include<stdio.h>
#include<stdlib.h>
typedef struct {
int first;
int pos;
}ElemType;
typedef struct node {
ElemType data;
struct node *next;
}queuenode;
typedef struct Head {
queuenode *front;
queuenode *rear;
int length;
}Queue;
void InitQueue (Queue *Q);
void Update (Queue *Q);//更新出列后在队列中的各数字的编号(新的位序)
void EnQueue (Queue *Q,ElemType e);
void DeQueue (Queue *Q,ElemType *x);
int Getlen (Queue *Q);
void Display (Queue *Q);
int main(void) {
int n, i, flag = 0;
scanf ("%d", &n);
Queue Q;
InitQueue (&Q);
for (i = 0; i < n; i++) {
ElemType e;
e.first = i + 1;
e.pos = i + 1;
EnQueue (&Q, e);
}
//printf ("%d",QueueLen(&Q));
if (n <= 3){
Display (&Q);
}
else{
while (1) {
flag++;
if (flag % 2){
int len = Getlen (&Q);
for (i = 0; i < len; i++){
ElemType x;
DeQueue (&Q, &x);
if (x.pos % 2) {
EnQueue (&Q, x);
}
}
//Update (&Q);
}
else{
int len = Getlen (&Q);//求队列长度不能放到for循环里,除了多增加计算量之外,队列长度会随着入队出队的操作变化,不是定值
for (i = 0; i < len; i++){
ElemType x;
DeQueue (&Q, &x);
if (x.pos % 3) {
EnQueue (&Q, x);
}
}
//Update (&Q);
}
Update (&Q);
if (Getlen (&Q) <= 3) break;
}
Display (&Q);
}
return 0;
return 0;
}
void InitQueue (Queue *Q) {
queuenode *p;
p = (queuenode*) malloc (sizeof (queuenode));
p->next = NULL;
Q->front = p;
Q->rear = p;
Q->length = 0;
}
void Update (Queue *Q) {
int i;
queuenode *p;
p = Q->front;
for (i = 0; i< Q->length; i++){
p->data.pos = i + 1;
p = p->next;
}
}
void EnQueue (Queue *Q, ElemType e) {
queuenode *p;
p = (queuenode*)malloc(sizeof(queuenode));
p->data= e;
p->next = NULL;
Q->rear->next = p;
Q->rear = p;
Q->length++;
//free(p);
}
void DeQueue(Queue *Q, ElemType *x) {
queuenode *p;
p = Q->front->next;
*x= Q->front->data;
Q->front = p;
Q->length--;
}
int Getlen(Queue *Q){
return Q->length;
}
void Display(Queue *Q){
queuenode *p;
p = Q->front;
while(p){
printf("%d ",p->data.first);
}
printf("\n");
}
数组实现
#include <stdio.h>
#define MAXSIZE 5005
int num[MAXSIZE];
int main (void) {
int n;
scanf ("%d", &n);
int i, count, temp;
temp = n;
//赋值
for (i = 1; i <= n; i++) {
num[i] = i;
}
//循环
while (temp > 3) {
count = 0;
for (i = 1; i <= n; i++){
if (num[i] == 0) continue;
else count++;//必须有else 否则continue会越过这句执行
if(count == 2) {
num[i] = 0;
count = 0;
}
}
temp -= temp / 2;
if (temp <= 3) break;
count = 0;
for (i = 1; i <= n; i++) {
if (num[i] == 0) continue;
else count++;
if (count == 3) {
num[i] = 0;
count = 0;
}
}
temp -= temp / 3;
}
for (i = 1; i <= n; i++) {
if (num[i]) printf ("%d ",num[i]);
}
printf ("\n");
return 0;
}
奇偶序列
输入一个整数组成的序列,然后将序列中的奇数位置结点依序放在前面,偶数位置结点依序放在后面,组成一个新的序列。输出此新序列。
输入共两行,第一行是一个正整数n,表示序列长度,n<100。第二行是n个整数,中间用空格隔开,表示序列中的元素。
在一行上输出新生成的序列,数字中间用空格隔开。
输入样例
7
10 2 30 4 50 60 7
输出样例
10 30 50 7 2 4 60
#include<stdio.h>
int main(void){
int n;
scanf("%d\n",&n);
int oushu[n],jishu[n];
int i,j=0,k=0,t;
for(i=0;i<n;i++){
scanf("%d",&t);
if((i+1)%2==0){
oushu[j] = t;
j++;
}
else{
jishu[k] = t;
k++;
}
}
for(i=0;i<k;i++){
printf("%d ",jishu[i]);
}
//printf("%d ",n);
for(i=0;i<j;i++){
printf("%d ",oushu[i]);
}
printf("\n");
return 0;
}
求next值
输入样例:
8
a b c a b c b c
输出样例
-1 0 0 0 1 2 3 0
#include<stdio.h>
#include<string.h>
void GetNext (char s[], int next[]);
int main(void) {
int n;
scanf ("%d", &n);
getchar();
char str[n];
int i;
for (i = 0; i < n; i++){
scanf ("%c", &str[i]);
getchar();
}
/*for (i = 0; i < n; i++){
printf ("%c", str[i]);
}*/
int next[n];
GetNext (str, next);
for (i = 0; i < n; i++){
printf ("%d ",next[i]);
}
printf("\n");
return 0;
}
void GetNext (char s[], int next[]) {
int i, j = -1;
i = 0;
next[0] = -1;
while (i < strlen (s)) {
if (j == -1 || s[i] == s[j]) {
++i;
++j;
next[i] = j;
}
else {
j = next[j];
}
}
}
判断回文字符串
输入样例:
abcba
abccba
abcfa
11221
输出样例
right
right
wrong
wrong
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 100
//顺序栈
typedef struct node{
char elements[MAXSIZE];
int Top;
}stack;
stack *setnull(stack *S); //初始化栈
char pop(stack *S); //出栈函数
stack push(stack *S, char e); //进栈函数
int correct(char String[],int len);//对输入的字符串,判断是否是回文,需要调用pop和push函数
stack *S;
int main(){
int sign;//1为回文,0为不是回文
int len;
char str[100];
S = (stack*)malloc(sizeof(stack));
setnull(S);
gets(str);
len = strlen(str);
sign = correct(str,len);
if(sign) printf("right\n");
else printf("wrong\n");
return 0;
}
stack *setnull(stack *S){
S->Top = -1;//Top指向栈顶元素,非栈顶元素的上一个
return S;
}
stack push(stack *S, char e){
S->Top++;
S->elements[S->Top] = e;
return *S;
}
char pop(stack *S){
char x;
if(S->Top != -1){//==-1 时返回值怎么搞?
x = S->elements[S->Top];
S->Top--;
}
return x;
}
int correct(char String[], int len){
int i,j,flag=0;
char e;
for(i=0;i<len;i++){
push(S,String[i]);
}
for(j=0;j<len/2;j++){
e = pop(S);
if(String[j]!=e){
flag = 0;
break;
}
else flag = 1;
}
return flag;
}
虽然判断回文用数组也可以实现,但是用栈的这个思路要熟悉。
中心对称的字符串
对于有n个字符的字符串,设计算法判断字符串是否中心对称。例如,xyzzyx和xyzyx都是中心对称的字符串。
每组数据有2行:第一行为整数n,表示字符的个数,n小于100;第二行为n个字符组成的字符串。
输出说明:
判断这个字符串是否是中心对称的,是输出“YES”,不是输出“NO”。
输入样例:
12
ThanksThanks
输出样例:
NO
#include<stdio.h>
#include<string.h>
#define maxsize 101
int main(void){
char s[maxsize];
int n;
scanf("%d\n",&n);
//getchar();
gets(s);
int i,flag = 0;
for(i=0; i<n/2; i++){
if(s[i]!=s[n-i-1]){
flag = 0;
break;
}
else{
flag = 1;
}
}
if(flag == 1){
printf("YES\n");
}
else{
printf("NO\n");
}
return 0;
}
这种方式和前面提到的栈的方式都要熟悉,还有一种方式是利用两个指针i,j从两端向中间遍历
最小周期串
如果一个字符串可以由某个长度为k的字符串重复多次得到,则该串以k为周期
输入一个长度不超过80的串,输出它的最小周期
输入样例
GeeGeeGee
输出样例
3
#include<stdio.h>
#include<string.h>
#define maxsize 81
int main(void){
char str[maxsize];
gets(str);
char a;
int i,j,len,index = 0;
len = strlen(str);
for(i=1;i<=len;i++){
if(len%i==0){
index = 1;
for(j=i;j<len;j++){
if(str[j]!=str[j%i]){
index = 0;
break;
}
}
if(index==1){
printf("%d\n",i);
break;
}
}
}
return 0;
}
重点是思路。
矩阵中的马鞍点
输入样例
4 4
2 7 9 10
1 0 7 12
8 23 13 15
4 6 12 18
输出样例
3 1 8
#include<stdio.h>
int main(void){
int n,m,i,j;
scanf("%d %d",&n,&m);
getchar();
int a[n][m];
//矩阵输入
for(i=0;i<n;i++){
for(j=0;j<m;j++){
scanf("%d",&a[i][j]);
}
}
int min,mincol,k,flag=0,index=0;
for(i=0;i<n;i++){
min = a[i][0];
mincol = 0;
for(j=0;j<m;j++){//寻找每一行的最小值
if(a[i][j]<min){
min = a[i][j];
mincol = j;
}
}
//判断列
flag = 1;
for(k=0;k<n;k++){
if(min<a[k][mincol]){//列中存在比这个点大的值,非马鞍点
flag = 0;
break;
}
}
if(flag == 1){
printf("%d %d %d\n",i+1,mincol+1,a[i][mincol]);
index = 1;
}
}
if(index==0){
printf("NO\n");
}
return 0;
}
矩阵对角线求和
整型矩阵
输入样例
1 2 3
4 5 6
7 8 9
输出样例
15
#include<stdio.h>
#include<stdarg.h>
int main(void){
int a[3][3];
int i,j,k,sum=0;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
scanf("%d",&a[i][j]);
}
}
for(k=0;k<3;k++){
sum +=a[k][k];
}
printf("%d\n",sum);
return 0;
}
矩阵相乘
A是23矩阵,B是32矩阵 计算A*B
输入样例
1 2 3
4 5 6
1 2
3 4
5 6
输出样例
22 28
49 64
#include<stdio.h>
int main(void){
int a[2][3],b[3][2],c[2][2];
int i,j,k;
for(i=0;i<2;i++){
for(j=0;j<3;j++){
scanf("%d ",&a[i][j]);
}
}
for(i=0;i<3;i++){
for(j=0;j<2;j++){
scanf("%d ",&b[i][j]);
}
}
for(i=0;i<2;i++){
for(j=0;j<2;j++){
c[i][j]= 0;
for(k=0;k<3;k++){
c[i][j] += a[i][k]*b[k][j];
}
}
}
for(i=0;i<2;i++){
for(j=0;j<2;j++){
printf("%d ",c[i][j]);
}
printf("\n");
}
return 0;
}
矩阵加法运算
稀疏矩阵
输入n,m,行列
样例输入
3 4
1 0 0 1
0 1 0 0
1 0 0 0
15 22 -6 9
0 1 1 0
0 1 1 0
1 0 0 1
3 2 6 2 -5 8
样例输出
1 1 1 1
0 0 1 0
1 0 0 1
15 3 2 22 4 8
#include<stdio.h>
#include<stdlib.h>
#define Row 20
#define Col 20
#define MAXSIZE 400
typedef struct{
int rows, cols, num;
int value[MAXSIZE + 1];//数组当中的非零元 数组名即指向首元素的指针
int map[Row + 1][Col + 1];//矩阵中相应元素是否为1
}Matrix;
void MatrixAdd (Matrix A, Matrix B, Matrix *C);
int main (void) {
Matrix A, B, C;
int n, m, i, j, num1 = 0, num2 = 0;
scanf ("%d %d", &n, &m);
/*矩阵A*/
A.rows = n;
A.cols = m;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
scanf ("%d", &A.map[i][j]);
if (A.map[i][j]) num1++;
}
}
A.num = num1;
for (i = 0; i < num1; i++) {
scanf ("%d", &A.value[i]);
}
/*矩阵B*/
B.rows = n;
B.cols = m;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
scanf ("%d", &B.map[i][j]);
if (B.map[i][j]) num2++;
}
}
B.num = num2;
for (i = 0; i < num2; i++) {
scanf ("%d", &B.value[i]);
}
MatrixAdd(A, B, &C);
return 0;
}
void MatrixAdd (Matrix A, Matrix B, Matrix *C) {
(*C).rows = A.rows;
(*C).cols = A.cols;
int i, j, pa = 0, pb = 0, pc = 0;
for (i = 0; i < A.rows; i++) {
for (j = 0; j < A.cols; j++) {
if (A.map[i][j] && B.map[i][j]) {
if (A.value[pa] + B.value[pb]) {
(*C).map[i][j] = 1;
(*C).value[pc] = A.value[pa] + B.value[pb];
pc++;
}
pa++;
pb++;
}
else if( A.map[i][j] && !B.map[i][j] ){
(*C).value[pc] = A.value[pa];
(*C).map[i][j] = 1;
pa++;
pc++;
}
else if( !A.map[i][j] && B.map[i][j] ){
(*C).value[pc] = B.value[pb];
(*C).map[i][j] = 1;
pb++;
pc++;
}
}
}
for (i = 0; i < (*C).rows; i++) {
for (j = 0; j < (*C).cols; j++) {
printf ("%d ",(*C).map[i][j]);
}
printf ("\n");
}
for (i = 0; i < pc; i++) {
printf ("%d ", (*C).value[i]);
}
printf ("\n");
}