第5-6周练习题 -- 函数题

2-1 Add Two Polynomials (20分)

Write a function to add two polynomials. Do not destroy the input.
Use a linked list implementation with a dummy head node.使用一个带有虚拟头结点的链表实现
Note: The zero polynomial is represented by an empty list with only the dummy head node.零多项式有一个只有虚拟头结点的空列表实现

Format of functions:

Polynomial Add( Polynomial a, Polynomial b );

where Polynomial is defined as the following:

typedef struct Node *PtrToNode;
struct Node {
    int Coefficient;
    int Exponent;
    PtrToNode Next;
};
typedef PtrToNode Polynomial;
/* Nodes are sorted in decreasing order of exponents.结点按指数的递减顺序排序*/  

The function Add is supposed to return a polynomial which is the sum of a and b.
Sample program of judge:

#include <stdio.h>
#include <stdlib.h>
typedef struct Node *PtrToNode;
struct Node  {
    int Coefficient;
    int Exponent;
    PtrToNode Next;
};
typedef PtrToNode Polynomial;

Polynomial Read(); /* details omitted */
void Print( Polynomial p ); /* details omitted */
Polynomial Add( Polynomial a, Polynomial b );

int main()
{
    Polynomial a, b, s;
    a = Read();
    b = Read();
    s = Add(a, b);
    Print(s);
    return 0;
}

/* Your function will be put here */

Sample Input:

4
3 4 -5 2 6 1 -2 0
3
5 20 -7 4 3 1

Sample Output:

5 20 -4 4 -5 2 9 1 -2 0

代码如下:
尾插法的应用

Polynomial Add( Polynomial a, Polynomial b ){
	Polynomial t1=a,t2=b,head,rear,tmp;
	head = (Polynomial)malloc(sizeof(struct Node));head->Next = NULL;
	rear = head;
	while(t1&&t2){
		if(t1->Exponent==t2->Exponent){
			if(t1->Coefficient+t2->Coefficient){
				Polynomial P = (Polynomial)malloc(sizeof(struct Node));
				P->Coefficient = t1->Coefficient+t2->Coefficient;P->Exponent=t1->Exponent;
				rear->Next = P;rear = P;  //尾插法
			}
			t1=t1->Next;t2=t2->Next;
		}else if(t1->Exponent<t2->Exponent){
			Polynomial P = (Polynomial)malloc(sizeof(struct Node));
			P->Coefficient = t2->Coefficient;P->Exponent=t2->Exponent;
			rear->Next = P;rear = P;  //尾插法
			t2=t2->Next;
		}else{
			Polynomial P = (Polynomial)malloc(sizeof(Polynomial));
			P->Coefficient = t1->Coefficient;P->Exponent=t1->Exponent;
			rear->Next = P;rear = P;  //尾插法
			t1=t1->Next;
		}
	}
	rear->Next=t1?t1:t2;  //相当于写循环把t1/t2剩下的结点一个个加到链表中
	return head;  //根据题意,空结点不用释放
}

2-2 学生成绩链表处理 (20分)

本题要求实现两个函数,一个将输入的学生成绩组织成单向链表;另一个将成绩低于某分数线的学生结点从链表中删除。

函数接口定义:

struct stud_node *createlist();
struct stud_node *deletelist( struct stud_node *head, int min_score );

函数createlist利用scanf从输入中获取学生的信息,将其组织成单向链表,并返回链表头指针。
链表节点结构定义如下:

struct stud_node {
    int              num;      /*学号*/
    char             name[20]; /*姓名*/
    int              score;    /*成绩*/
    struct stud_node *next;    /*指向下个结点的指针*/
};

输入为若干个学生的信息(学号、姓名、成绩),当输入学号为0时结束。
函数deletelist从以head为头指针的链表中删除成绩低于min_score的学生,并返回结果链表的头指针。

裁判测试程序样例:

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

struct stud_node {
     int    num;
     char   name[20];
     int    score;
     struct stud_node *next;
};

struct stud_node *createlist();
struct stud_node *deletelist( struct stud_node *head, int min_score );

int main()
{
    int min_score;
    struct stud_node *p, *head = NULL;

    head = createlist();
    scanf("%d", &min_score);
    head = deletelist(head, min_score);
    for ( p = head; p != NULL; p = p->next )
        printf("%d %s %d\n", p->num, p->name, p->score);

    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

1 zhang 78
2 wang 80
3 li 75
4 zhao 85
0
80

输出样例:

2 wang 80
4 zhao 85

代码如下:
链表的建立和删除操作
核心:尾插法 和 删除当前节点需要知道当前结点的前一个结点的位置

struct stud_node *createlist(){
	struct stud_node *h,*r,*tmp,*P;
	h = (struct stud_node *)malloc(sizeof(struct stud_node));
	r = h;
	int num,score;char sname[20];
	scanf("%d",&num);
	while(num){
		scanf("%s %d",sname,&score);
		P = (struct stud_node *)malloc(sizeof(struct stud_node));P->next=NULL;
		P->num = num;P->score=score;
		strcpy(P->name,sname);  //P->name=sname;
		r->next = P;r = P;
		scanf("%d",&num);
	}
	tmp = h;h=h->next;free(tmp);  //由主函数里的输出语句可知返回的指针不带空头结点
	return h;   //有的博客没有上一行删除空结点的操作直接返回h->next,此法虽简单但是内存会有一个没使用的空间
}

struct stud_node *deletelist( struct stud_node *head, int min_score ){   
    struct stud_node *p1,*p2;
    p1=p2=head;
    while(head!=NULL&&head->score<min_score){
        head=head->next;
        p1=p2=head;
    }
    while(p2!=NULL){
        p2=p2->next;  //当前p2是刚从上一个while循环里出来的score>=min_score,所以让p2指向自己下一个
        if(p2==NULL) return head;
        else if(p2->score<min_score){
            p1->next=p2->next;
            p2=p1;
        }else p1=p1->next;  //p1始终是p2的前一个结点,删除操作必须要知道当前结点的前一个结点的位置
    }
    return head;
}

2-3 链表拼接 (20分)

本题要求实现一个合并两个有序链表的简单函数。

链表结点定义如下:

struct ListNode {
    int data;
    struct ListNode *next;
};

函数接口定义:

struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);

其中list1list2是用户传入的两个按data升序链接的链表的头指针;函数mergelists将两个链表合并成一个按data升序链接的链表,并返回结果链表的头指针。

裁判测试程序样例:

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

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *createlist(); /*裁判实现,细节不表*/
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);
void printlist( struct ListNode *head )
{
     struct ListNode *p = head;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode  *list1, *list2;

    list1 = createlist();
    list2 = createlist();
    list1 = mergelists(list1, list2);
    printlist(list1);
	
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

1 3 5 7 -1
2 4 6 -1

输出样例:

1 2 3 4 5 6 7 

代码如下:

struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2){
    if(!list1&&!list2) return NULL;
    int flag=0;
	struct ListNode *h = NULL,*r,*P;
    r = h;
	while(list1&&list2){
		P = (struct ListNode *)malloc(sizeof(struct ListNode));P->next = NULL;
		P->data = list1->data<list2->data ? list1->data : list2->data;
        if(!flag){
            h = P;
            r = h;
            flag=1;
        }else{
            r->next = P;
            r = P;
        }
        if(list1->data<list2->data) list1=list1->next;
        else list2=list2->next;
	}
	r->next=list1?list1:list2;
	return h;
}

2-4 另类堆栈 (20分)

在栈的顺序存储实现中,另有一种方法是将Top定义为栈顶的上一个位置。请编写程序实现这种定义下堆栈的入栈、出栈操作。如何判断堆栈为空或者满?

函数接口定义:

bool Push( Stack S, ElementType X );
ElementType Pop( Stack S );

其中Stack结构定义如下:

typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
    ElementType *Data;  /* 存储元素的数组 */
    Position Top;       /* 栈顶指针       */
    int MaxSize;        /* 堆栈最大容量   */
};
typedef PtrToSNode Stack;

注意:如果堆栈已满,Push函数必须输出“Stack Full”并且返回false;如果堆栈是空的,则Pop函数必须输出“Stack Empty”,并且返回ERROR

裁判测试程序样例:

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

#define ERROR -1
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode {
    ElementType *Data;  /* 存储元素的数组 */
    Position Top;       /* 栈顶指针       */
    int MaxSize;        /* 堆栈最大容量   */
};
typedef PtrToSNode Stack;

Stack CreateStack( int MaxSize )
{
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));
    S->Top = 0;
    S->MaxSize = MaxSize;
    return S;
}

bool Push( Stack S, ElementType X );
ElementType Pop( Stack S );

Operation GetOp();          /* 裁判实现,细节不表 */
void PrintStack( Stack S ); /* 裁判实现,细节不表 */

int main()
{
    ElementType X;
    Stack S;
    int N, done = 0;

    scanf("%d", &N);
    S = CreateStack(N);
    while ( !done ) {
        switch( GetOp() ) {
        case push: 
            scanf("%d", &X);
            Push(S, X);
            break;
        case pop:
            X = Pop(S);
            if ( X!=ERROR ) printf("%d is out\n", X);
            break;
        case end:
            PrintStack(S);
            done = 1;
            break;
        }
    }
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

4
Pop
Push 5
Push 4
Push 3
Pop
Pop
Push 2
Push 1
Push 0
Push 10
End

输出样例:

Stack Empty
3 is out
4 is out
Stack Full
0 1 2 5 

代码如下:

bool Push( Stack S, ElementType X ){
	if(S->Top==S->MaxSize){ 
		printf("Stack Full\n");
		return false;
	}
	S->Data[S->Top++] = X;  //S->Top是当前元素上一个位置正好为空直接装入然后S->Top指向再上一个
	return true; 
}
ElementType Pop( Stack S ){
	if(S->Top==0){
		printf("Stack Empty\n");
		return ERROR;
	}
	return S->Data[--S->Top];
}

2-5 Two Stacks In One Array (20分)

Write routines to implement two stacks using only one array. Your stack routines should not declare an overflow unless every slot in the array is used. 除非使用数组的每一个空间否则堆栈不应声明溢出

Format of functions:

Stack CreateStack( int MaxElements );
int IsEmpty( Stack S, int Stacknum );
int IsFull( Stack S );
int Push( ElementType X, Stack S, int Stacknum );
ElementType Top_Pop( Stack S, int Stacknum );

where int Stacknum is the index of a stack which is either 1 or 2; int MaxElements is the size of the stack array; and Stack is defined as the following:

typedef struct StackRecord *Stack;
struct StackRecord  {
    int Capacity;       /* maximum size of the stack array */
    int Top1;           /* top pointer for Stack 1 */
    int Top2;           /* top pointer for Stack 2 */
    ElementType *Array; /* space for the two stacks */
}

Note: Push is supposed to return 1 if the operation can be done successfully, or 0 if fails. If the stack is empty, Top_Pop must return ERROR which is defined by the judge program.

Sample program of judge:

#include <stdio.h>
#include <stdlib.h>
#define ERROR 1e8
typedef int ElementType;
typedef enum { push, pop, end } Operation;

typedef struct StackRecord *Stack;
struct StackRecord  {
    int Capacity;       /* maximum size of the stack array */
    int Top1;           /* top pointer for Stack 1 */
    int Top2;           /* top pointer for Stack 2 */
    ElementType *Array; /* space for the two stacks */
};

Stack CreateStack( int MaxElements );
int IsEmpty( Stack S, int Stacknum );
int IsFull( Stack S );
int Push( ElementType X, Stack S, int Stacknum );
ElementType Top_Pop( Stack S, int Stacknum );

Operation GetOp();  /* details omitted */
void PrintStack( Stack S, int Stacknum ); /* details omitted */

int main()
{
    int N, Sn, X;
    Stack S;
    int done = 0;

    scanf("%d", &N);
    S = CreateStack(N);
    while ( !done ) {
        switch( GetOp() ) {
        case push: 
            scanf("%d %d", &Sn, &X);
            if (!Push(X, S, Sn)) printf("Stack %d is Full!\n", Sn);
            break;
        case pop:
            scanf("%d", &Sn);
            X = Top_Pop(S, Sn);
            if ( X==ERROR ) printf("Stack %d is Empty!\n", Sn);
            break;
        case end:
            PrintStack(S, 1);
            PrintStack(S, 2);
            done = 1;
            break;
        }
    }
    return 0;
}

/* Your function will be put here */

Sample Input:

5
Push 1 1
Pop 2
Push 2 11
Push 1 2
Push 2 12
Pop 1
Push 2 13
Push 2 14
Push 1 3
Pop 2
End

Sample Output:

Stack 2 is Empty!
Stack 1 is Full!
Pop from Stack 1: 1
Pop from Stack 2: 13 12 11

代码如下:

Stack CreateStack( int MaxElements ){
	Stack S = (Stack)malloc(sizeof(struct StackRecord));
	S->Array = (ElementType *)malloc(MaxElements*sizeof(ElementType));
	S->Capacity	 = MaxElements;
	S->Top1 = -1;
	S->Top2 = MaxElements;
	return S;
}
int IsEmpty( Stack S, int Stacknum ){
	if(Stacknum==1&&S->Top1==-1) return 1;
    else if(Stacknum==2&&S->Top2==S->Capacity) return 1;
    return 0;
}
int IsFull( Stack S ){
	return S->Top2-S->Top1==1?1:0;
}
int Push( ElementType X, Stack S, int Stacknum ){
	if(IsFull(S)) return 0;
	if(Stacknum==1) S->Array[++(S->Top1)]=X;
	else S->Array[--(S->Top2)]=X;
	return 1;
}
ElementType Top_Pop( Stack S, int Stacknum ){
	if(IsEmpty(S,Stacknum)) return ERROR;
	if(Stacknum==1) return S->Array[(S->Top1)--];
	else return S->Array[(S->Top2)++];
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值