Data_structure_book上的一些例题

例题1:

//通过键盘输入一组多项式的系数和指数,用尾插法建立一元多项式的链表。
//以输入系数为0为结束标志,并约定建立多项式链表时,总是按指数从小到大的顺序排列

#include<stdio.h>
#include<stdlib.h>

typedef struct Polynode
{
    int coef;
    int exp;
    struct Polynode *next;
}Polynode,*PolyList;

void input(PolyList LA);
PolyList PolyAdd(PolyList LA,PolyList LB);
void output(PolyList LC);

int main()
{
    PolyList LA,LB,LC;
    LA=(PolyList)malloc(sizeof(Polynode));
    LB=(PolyList)malloc(sizeof(Polynode));
    input(LA);
    input(LB);
    LC=PolyAdd(LA,LB);
    output(LC);
    return 0;
}

void input(PolyList LA)
{
    Polynode *tail,*s;
    int c,e;
    tail=LA;
    scanf("%d %d",&c,&e);
    while(c){
        s=(Polynode *)malloc(sizeof(Polynode));
        if(s!=NULL){
            s->coef=c;
            s->exp=e;
            tail->next=s;
            tail=s;
            scanf("%d %d",&c,&e);
        }
    }
    tail->next=NULL;
}

PolyList PolyAdd(PolyList LA,PolyList LB)
{
    Polynode *p,*q,*tail,*temp;
    int sum;
    p=LA->next;
    q=LB->next;
    tail=LA;
    while(p!=NULL&&q!=NULL){
        if(p->exp<q->exp){
            tail->next=p;
            tail=p;
            p=p->next;
        }
        else if(p->exp==q->exp){
            sum=p->coef+q->coef;
            if(sum!=0){
                p->coef=sum;
                tail->next=p;
                tail=p;
                p=p->next;
                temp=q;
                q=q->next;
                free(temp);
            }
            else{
                temp=p;
                p=p->next;
                free(temp);
                temp=q;
                q=q->next;
                free(temp);
            }
        }
        else{
            tail->next=q;
            tail=q;
            q=q->next;
        }
    }
    if(p){
        tail->next=p;
    }
    else{
        tail->next=q;
    }
    free(LB);
    return LA;
}
void output(PolyList LC)
{
    Polynode *p;
    p=LC->next;
    while(p!=NULL){
        printf("%d %d\n",p->coef,p->exp);
        p=p->next;
    }
}

核心部分:
一元多项式的相加运算中分为三种情况:
(1) p->exp < q->exp;
(2) p->exp==q->exp;
(3)p->exp > q->exp;
写代码中注意使用malloc函数时可以另外再申请一个指针变量指向其所申请的空间地址;另外注意使用PolyList和Polynode *定义指针时候的区别。

例题2:括号匹配问题(利用栈的特点)

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1;
#define FALSE 0;

typedef struct node
{
    char a;
    struct node *next;
}StackNode,*LinkNode;

void bracketmatch(char *str);
void InitStack(LinkNode *S);
void push(char str,LinkNode S);
int IsEmpty(LinkNode S);
int Match(char str,LinkNode S);
void pop(LinkNode S);

int main()
{
    char str[100];
    scanf("%s",str);
    bracketmatch(str);
    return 0;
}

void bracketmatch(char *str)
{
    LinkNode S;
    int i;
    InitStack(&S);
    for(i=0;str[i]!='\0';i++){
        switch(str[i])
        {
            case '(':
            case '[':
            case '{':
            {
                push(str[i],S);
                break;
            }
            case ')':
            case ']':
            case '}':
            {
                if(IsEmpty(S)){
                    printf("右括号多余!\n");
                    return;
                }
                else{
                    if(Match(str[i],S))pop(S);
                    else{
                        printf("括号不匹配!\n");
                        return;
                    }
                }
                break;
            }
            default :
            {
                printf("输入错误!");
                return;
            }
        }
    }
    if(IsEmpty)printf("括号匹配!\n");
    else printf("左括号多余!\n");
}

void InitStack(LinkNode *S)
{
    *S=(LinkNode)malloc(sizeof(StackNode));
    (*S)->next=NULL;
}

void push(char str,LinkNode S)
{
    StackNode *p;
    p=(StackNode *)malloc(sizeof(StackNode));
    if(p!=NULL){
        p->a=str;
        p->next=S->next;
        S->next=p;
    }
}

int IsEmpty(LinkNode S)
{
    if(S->next==NULL){
        return TRUE;
    }
    else return FALSE;
}

int Match(char str,LinkNode S)
{
    switch(str)
    {
        case '(':
        {
            if(S->next->a==')')
            {
                return TRUE;
            }
            else return FALSE;
        }
        case '[':
        {
            if(S->next->a==']')
            {
                return TRUE;
            }
            else return FALSE;
        }
        case '{':
        {
            if(S->next->a=='}')
            {
                return TRUE;
            }
            else return FALSE;
        }
    }
}

void pop(LinkNode S)
{
    StackNode *temp;
    temp=S->next;
    S->next=temp->next;
    free(temp);
}

注意:
(1)链表和栈的初始化中,是(S)->next=NULL;而不是S->next=NULL;
(2)

if(S->next->a==']') return TRUE;
else return FALSE;

此代码编译器会报错“else没有相应的if与之匹配!”,而应改写成:

if(S->next->a==']'){
	return TRUE;
}
else return FALSE;

例题3:无括号算数运算(+、-、*、/)

#include<stdio.h>
#include<stdlib.h>

typedef struct ovsnode
{
    int num;
    struct ovsnode *next;
}OvsNode,*LinkOvsNode;

typedef struct optrnode
{
    char a;
    struct optrnode *next;
}OptrNode,*LinkOptrNode;

int operation2(char *str);
void InitStack1(LinkOvsNode *A);
void InitStack2(LinkOptrNode *B);
void push1(int y,LinkOvsNode A);
void push2(char y,LinkOptrNode B);
void pop1(int *a,LinkOvsNode A);
void pop2(char *m,LinkOptrNode B);
int gettop(LinkOvsNode A);
int operation(int a,char m,int b);
char campare(char str,LinkOptrNode B);
int main()
{
    char str[100];
    int n;
    scanf("%s",str);
    n=operation2(str);
    printf("%d",n);
    return 0;
}
int operation2(char *str)
{
    int i,y;
    int a,b,c;
    int n;
    char x,m;
    LinkOvsNode A;
    LinkOptrNode B;
    OptrNode *p;
    InitStack1(&A);
    InitStack2(&B);
    //int g=0;
    for(i=0;str[i]!='\0';i++){
        x=str[i];
        if(x>='0'&&x<='9')
        {//数字
            y=x-48;
          //  printf("%d\n",y);
            push1(y,A);
        }
        else{
            if(B->next!=NULL)
            {
               switch(campare(str[i],B))
               {
                   case '>':
                   {
                       push2(str[i],B);
                    //   printf("%c",B->next->a);
                       break;
                   }
                   case '=':
                   case '<':
                   {
                       pop1(&a,A);
                       pop1(&b,A);
                       pop2(&m,B);
                       c=operation(a,m,b);
                       push1(c,A);
                       push2(str[i],B);
                       break;
                   }
               }
            }
            else
            {
                push2(str[i],B);
            }
        }
    }
    p=B;
//    int k=0;
 //   printf("%c",p->a);
    while(p->next!=NULL){
   //     k++;
   //     printf("%d\n",k);
        pop1(&a,A);
  //      printf("%d\n",a);
        pop1(&b,A);
  //      printf("%d\n",a);
        pop2(&m,B);
    //    printf("%c\n",m);
        c=operation(a,m,b);
  //      printf("%d\n",c);
        push1(c,A);
    }
   // if(p==NULL)printf("p is NULL");
    n=A->next->num;
    free(A);
    free(B);
    return n;
}
void InitStack1(LinkOvsNode *A)
{
    *A=(LinkOvsNode)malloc(sizeof(OvsNode));
    (*A)->next=NULL;
}
void InitStack2(LinkOptrNode *B)
{
    *B=(LinkOptrNode)malloc(sizeof(OptrNode));
    (*B)->next=NULL;
}
void push1(int y,LinkOvsNode A)
{
    OvsNode *p;
    p=(OvsNode*)malloc(sizeof(OvsNode));
    if(p!=NULL){
        p->num=y;
        p->next=A->next;
        A->next=p;
 //       printf("%d\n",A->next->num);
    }
}
void push2(char y,LinkOptrNode B)
{
    OptrNode *p;
    p=(OptrNode*)malloc(sizeof(OptrNode));
    if(p!=NULL){
        p->a=y;
        p->next=B->next;
        B->next=p;
//        printf("%c",B->next->a);
    }
}
void pop1(int *a,LinkOvsNode A)
{
    OvsNode *temp;
    temp=A->next;
    *a=temp->num;
 //   printf("%d\n",*a);
    A->next=temp->next;
    free(temp);
}
void pop2(char *m,LinkOptrNode B)
{
    OptrNode *temp;
    temp=B->next;
    *m=temp->a;
    B->next=temp->next;
    free(temp);
}
int operation(int a,char m,int b)
{
    int c;
    switch(m)
    {
        case '+':c=a+b;break;
        case '-':c=a-b;break;
        case '*':c=a*b;break;
        case '/':c=a/b;break;
    }
    return c;
}
char campare(char str,LinkOptrNode B)
{
    char s;
    s=B->next->a;
   // printf("%c",s);
    switch(str)
    {
        case '+':
            {
                switch(s)
                {
                    case '+':
                    case '-':return '=';break;
                    case '*':
                    case '/':return '<';break;
                }
                break;
            }
        case '-':
            {
                switch(s)
                {
                    case '+':
                    case '-':return '=';break;
                    case '*':
                    case '/':return '<';break;
                }
                break;
            }
        case '*':
            {
                switch(s)
                {
                    case '+':
                    case '-':return '>';break;
                    case '*':
                    case '/':return '=';break;
                }
                break;
            }
        case '/':
            {
                switch(s)
                {
                    case '+':
                    case '-':return '>';break;
                    case '*':
                    case '/':return '=';break;
                }
            }
    }
}

注意:下面的代码中,注意在while循环中不能再使用p=p->next;来作为循环的控制语句。由于在while循环中调用了pop(出栈)函数,而出栈函数也就相当于隐式地释放了之前申请的内存空间,若继续使用p=p->next这样的控制语句,就会使得p指针变为迷途指针,使程序出现问题。所以只要有p->next!=NULL这个语句就欧克了。(这其中也体现了栈的后进先出的特点以及头插法建立链表的特点)

 	p=B;
//    int k=0;
 //   printf("%c",p->a);
    while(p->next!=NULL){
   //     k++;
   //     printf("%d\n",k);
        pop1(&a,A);
  //      printf("%d\n",a);
        pop1(&b,A);
  //      printf("%d\n",a);
        pop2(&m,B);
    //    printf("%c\n",m);
        c=operation(a,m,b);
  //      printf("%d\n",c);
        push1(c,A);
    }

例题四:打印杨辉三角前n行元素

//打印杨辉三角前n行元素
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100

typedef struct
{
    int a[MAXSIZE];
    int front;
    int rear;
}SeqQueue;
void InitQueue(SeqQueue *Q);
void PrintYhsj(SeqQueue *Q,int n);
int main()
{
    int n;
    SeqQueue *Q;
    Q=(SeqQueue*)malloc(sizeof(SeqQueue));
    scanf("%d",&n);
    InitQueue(Q);
    PrintYhsj(Q,n);
    return 0;
}
void InitQueue(SeqQueue *Q)
{
    Q->front=Q->rear=0;
}
void PrintYhsj(SeqQueue *Q,int n)
{
    int i,j,k,m;
    int flag=0;
    for(j=1;j<=n-1;j++)printf(" ");
    printf("1\n");
    if(n>=2){
        Q->a[Q->rear]=1;
        Q->rear=(Q->rear+1)%MAXSIZE;
        Q->a[Q->rear]=1;
        Q->rear=(Q->rear+1)%MAXSIZE;
        for(k=2;k<=n;k++){//n行
            for(m=1;m<=n-k;m++)printf(" ");//前面空格
            if(n==2){
                flag=1;
                printf("1 1\n");
                break;
            }
            else{
                Q->a[Q->rear]=1;
                Q->rear=(Q->rear+1)%MAXSIZE;
                for(i=1;i<=k-1;i++){//输出中间k-2个元素!!!
                    Q->a[Q->rear]=Q->a[Q->front]+Q->a[(Q->front+1)%MAXSIZE];
                    Q->rear=(Q->rear+1)%MAXSIZE;
                    printf("%d ",Q->a[Q->front]);
                    Q->front=(Q->front+1)%MAXSIZE;
                }
                printf("%d ",Q->a[Q->front]);
                Q->front=(Q->front+1)%MAXSIZE;
                Q->a[Q->rear]=1;
                Q->rear=(Q->rear+1)%MAXSIZE;
                printf("\n");
            }
        }
    }
}

核心部分:利用队列先进先出的特点输出杨辉三角的元素。
此外要掌握循环队列的使用方法:
Q->front=(Q->front+1)%MAXSIZE;//出队
Q->rear=(Q->rear+1)%MAXSIZE;//入队
注意:此代码实际上是利用队列中上一行的元素出队得出下一行的元素(入队)。在上面的代码中
for(i=1;i<=k-1;i++){//输出中间k-2个元素!!!
为什么是k-1而不是k-2?
此时要考虑的应该是计算机存储了下一行元素,因为只有存储了下一行元素,上一行元素才会全部输出,而此代码中的k仅表示“输出”第k行,所以具体考虑的是k+1行,而k+1行要入队存储(k+1)-2=k-1个中间元素,所以for的控制条件应该是i<=k-1.

例题5:有两个进程同时存在于一个程序中。其中第一个进程在屏幕上连续显示字符“A”,与此同时,程序不断检测键盘是否有输入,如果有的话,就读入用户输入的字符并保存到输入缓冲区中。在用户输入时,输入的字符并不立即回显到屏幕上。当用户输入一个逗号(,)或分号(;)时,表示第一个进程结束,第二个进程从缓冲区中读取那些已输入的字符并显示到屏幕上。第二个进程结束后,程序又进入第一个进程,重新显示字符“A”,同时用户又可以继续输入字符,直到用户输入一个分号键,才结束第一个进程,同时也结束整个程序。

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
//#include"queue.h"
#define MAXSIZE 10

typedef struct
{
    char s[MAXSIZE];
    int front;
    int rear;
}SeqQueue;
void Initqueue(SeqQueue *Q);
int EnterQueue(char ch1,SeqQueue *Q);
int IsEmpty(SeqQueue *Q);
void DeleteQueue(SeqQueue *Q,char *ch2);
int main()
{
    char ch1,ch2;
    int flag;
    SeqQueue *Q;
    Initqueue(Q);
    for(;;){
        for(;;){//第一个进程
            printf("A");
            if(kbhit()){
                ch1=getch();
                if(ch1==','||ch1==';')break;
                flag=EnterQueue(ch1,Q);
                if(flag==0){
                    printf("队列已满!");
                    break;
                }
            }
        }
        while(!IsEmpty(Q)){//第二个进程
            DeleteQueue(Q,&ch2);
            putchar(ch2);
        }
        if(ch1==';')break;
    }
    return 0;
}
void Initqueue(SeqQueue *Q)
{
    Q=(SeqQueue*)malloc(sizeof(SeqQueue));
    Q->front=Q->rear=0;
}
int EnterQueue(char ch1,SeqQueue *Q)
{
    if(Q->front!=(Q->rear+1)%MAXSIZE){
        Q->s[Q->rear]=ch1;
        Q->rear=(Q->rear+1)%MAXSIZE;
        return 1;
    }
    else return 0;
}
int IsEmpty(SeqQueue *Q)
{
    if(Q->front==Q->rear)return 1;
    else return 0;
}
void DeleteQueue(SeqQueue *Q,char *ch2)
{
    *ch2=Q->s[Q->front];
    Q->front=(Q->front+1)%MAXSIZE;
}

函数kbhit()是: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 。
getchar()与getch()的区别:
1.getchar();从键盘读取一个字符并bai输出,该函数du的返回值是输入zhi第一个字符的ASCII码;
若用户输入的是一连串dao字符,函数直到用户输入回车时结束,输入的字符连同回车一起存入键盘缓冲区。
若程序中有后继的getchar();函数,则直接从缓冲区逐个读取已输入的字符并输出,直到缓冲区为空时才重新读取用户的键盘输入。
2.getch();接受一个任意键的输入,不用按回车就返回。
该函数的返回值是所输入字符的ASCII码,且该函数的输入不会自动显示在屏幕上,需要putchar();函数输出显示。
getch();函数常用于中途暂停程序方便调试和查看。
3.getchar();和getch();的另一个区别就是所需要包含的头文件不同。
getchar();用#include<stdio.h>
getch(); 用#include<conio.h>

例题六:用列序递增法实现稀疏矩阵的转置

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100

typedef struct
{
    int row,col;
    int e;
}Triple;

typedef struct
{
    Triple data[MAXSIZE+1];
    int m,n;
    int len;
}MSTriple;
void Input(MSTriple *Q);
MSTriple *TransTriple(MSTriple *Q);
void Output(MSTriple *p);
int main()
{
    MSTriple *Q,*p;
    Q=(MSTriple*)malloc(sizeof(MSTriple));
    Input(Q);
    p=TransTriple(Q);
    if(p!=NULL)Output(p);
    return 0;
}

void Input(MSTriple *Q)
{
    int m,n;
    int x,y,z;
    int i,j;
    scanf("%d %d",&m,&n);
    Q->m=m;
    Q->n=n;
    Q->len=0;
    scanf("%d %d %d",&x,&y,&z);
    for(i=1;x!=0&&y!=0&&z!=0&&i<=MAXSIZE;i++){
        Q->data[i].row=x;
        Q->data[i].col=y;
        Q->data[i].e=z;
        Q->len++;
        scanf("%d %d %d",&x,&y,&z);
    }
}
MSTriple *TransTriple(MSTriple *Q)
{
    MSTriple *p;
    int i,j,k=1;
    p=(MSTriple *)malloc(sizeof(MSTriple));
    p->len=Q->len;
    p->m=Q->n;
    p->n=Q->m;
    if(p->len>0){
        for(j=1;j<=p->n;j++){
            for(i=1;i<=Q->len;i++){
                if(Q->data[i].col==j){
                    p->data[k].row=Q->data[i].col;
                    p->data[k].col=Q->data[i].row;
                    p->data[k].e=Q->data[i].e;
                    k++;
                }
            }
        }
        return p;
    }
    else return NULL;
}

void Output(MSTriple *p)
{
    int i;
    for(i=1;i<=p->len;i++){
        printf("%d %d %d\n",p->data[i].row,p->data[i].col,p->data[i].e);
    }
}

核心部分:不断地遍历原三元组元素,对原三元组列序进行不断地筛选达到排序的效果,以至于实现新三元组的行数是递增的。

例题七:利用一次定位法实现矩阵的转置。

#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100

typedef struct
{
    int row,col;
    int e;
}Triple;

typedef struct
{
    Triple data[MAXSIZE+1];
    int m,n,len;
}MSTriple;

void InitTriple(MSTriple *A);
void Input(MSTriple *A);
MSTriple *TransTriple(MSTriple *A);
void Ouput(MSTriple *B);

int main()
{
    MSTriple *A,*B;
    A=(MSTriple*)malloc(sizeof(MSTriple));
    InitTriple(A);
    Input(A);
    B=TransTriple(A);
    Ouput(B);
    return 0;
}
void InitTriple(MSTriple *A)
{
    A->m=0;
    A->n=0;
    A->len=0;
}
void Input(MSTriple *A)
{
    int m,n;
    int x,y,z;
    int i;
    scanf("%d %d",&m,&n);
    A->m=m;
    A->n=n;
    scanf("%d %d %d",&x,&y,&z);
    for(i=1;x!=0&&y!=0&&z!=0&&A->len<=MAXSIZE;i++){
        A->data[i].row=x;
        A->data[i].col=y;
        A->data[i].e=z;
        A->len++;
        scanf("%d %d %d",&x,&y,&z);
    }
}

MSTriple *TransTriple(MSTriple *A)
{
    MSTriple *B;
    int i,j,k;
    int num[100],position[100];
    B=(MSTriple*)malloc(sizeof(MSTriple));
    B->len=A->len;
    B->m=A->n;
    B->n=A->m;
    //要遍历A中每一个非零元素,记录B中每行的元素个数
    for(i=1;i<=A->n;i++)num[i]=0;//注意!!!
    for(i=1;i<=A->len;i++)num[A->data[i].col]++;
    //记录B中每行第一个元素的下标值
    position[1]=1;
    for(i=2;i<=A->n;i++)position[i]=position[i-1]+num[i-1];
    //遍历A中的元素,进行转置操作
    for(i=1;i<=A->len;i++){//核心部分
        j=A->data[i].col;
        k=position[j];
        B->data[k].row=A->data[i].col;
        B->data[k].col=A->data[i].row;
        B->data[k].e=A->data[i].e;
        position[j]++;
    }
    return B;
}
void Ouput(MSTriple *B)
{
    int i;
    for(i=1;i<=B->len;i++){
        printf("%d %d %d\n",B->data[i].row,B->data[i].col,B->data[i].e);
    }
}

注意1:在对num[100]进行初始化的时候,应该是要求B中每一行的num[ ]均初始化为0;不能仅初始化非零元素的num[ ]。如下:
正确:

    for(i=1;i<=A->n;i++)num[i]=0;//注意!!!

错误:

for(i=0;i<=A->len;i++)num[A->data[i].col]=0;

如果使用了后面错误的代码,会造成后面position[i]=position[i-1]+num[i-1];计算错误,因为可能会遇到未进行初始化的num[i-1]!!!
注意2:顺序结构类型的对象初始化的时候要像链表初始化的时候一样:

void InitTriple(MSTriple **A)
{
    *A=(MSTriple*)malloc(sizeof(MSTriple));
    (*A)->m=0;
    (*A)->n=0;
    (*A)->len=0;
}

当然也可以在调用函数内部给对象分配空间,然后再调用一个初始化的函数,如此代码中的使用。

核心部分:position[col]存储的是每一行中第一个非零元素在B中的下标值,通过position[col]++;实现B中存储col行下一个非零元素。可以把position[col]看成是一个在col行上的一个指针,这个指针指向在col行上下一个非零元素在B中的下标值。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DrmBee#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值