<数据结构|期末总结>OJ部分代码及思路总结(一)

线性表

反转链表

思路:运用三个指针(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&&current2){
        //两张表均不为空
        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");
}

难点是判断函数,如何根据栈空判断

括号配对问题

输入样例
3
[(])
(])
([])

输出样例
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+2
3-
输出样例
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");
}

树、图、查找

<数据结构|期末总结>OJ部分代码及思路总结(二)

排序

<数据结构|期末总结>OJ部分代码及思路总结(三)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值