1. 程式人生 > 實用技巧 >SDUST /PTA 近期函式題彙總

SDUST /PTA 近期函式題彙總

01二分演算法查詢

函式介面定義

Position BinarySearch( List L, ElementType X );

其中List結構定義如下:

typedef int Position;
typedef struct LNode *List;
struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 儲存線性表中最後一個元素的位置 */
};

L是使用者傳入的一個線性表,其中ElementType元素可以通過>、==、<進行比較,並且題目保證傳入的資料是遞增有序的。函式BinarySearch

要查詢XData中的位置,即陣列下標(注意:元素從下標1開始儲存)。找到則返回下標,否則返回一個特殊的失敗標記NotFound

裁判測試程式樣例:

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

#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;

typedef int Position;
typedef struct LNode *List;
struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 儲存線性表中最後一個元素的位置 */
};

List ReadInput(); /* 裁判實現,細節不表。元素從下標1開始儲存 */
Position BinarySearch( List L, ElementType X );

int main()
{
    List L;
    ElementType X;
    Position P;

    L = ReadInput();
    scanf("%d", &X);
    P = BinarySearch( L, X );
    printf("%d\n", P);

    return 0;
}

/* 你的程式碼將被嵌在這裡 */

輸入樣例1:

5
12 31 55 89 101
31

輸出樣例1:

2

輸入樣例2:

3
26 78 233
31

輸出樣例2

分析:很簡單的一道題,先是用正常的二分查詢找了一遍,後來發現直接順序查詢也可以通過(老懶狗了

Position BinarySearch( List L, ElementType X )
{
    int low=1;
    int high=L->Last;
    int flag=-1;
    int mid;
    
    while(low<=high)
    {
        mid=(mid+high)/2;
        if(X==L->Data[mid])
        {
            flag=mid;
            break;
        }
        else if(X<L->Data[mid])
            high=mid-1;
        else
            low=mid;
    }
  
    if(flag>0)
        return flag;
    else 
        return NotFound;
}
Position BinarySearch( List L, ElementType X )
{
    int i=1;
    int flag=-1;
    for(i=1;i<=L->Last;i++)
    {
        if(L->Data[i]==X)
        {
            flag=i;
            break;
        }
    }
    if(flag>0)
        return flag;
    else 
        return NotFound;
}

02連結串列逆置

本題要求實現一個函式,將給定單向連結串列逆置,即表頭置為表尾,表尾置為表頭。連結串列結點定義如下:

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

函式介面定義:

struct ListNode *reverse( struct ListNode *head );

其中head是使用者傳入的連結串列的頭指標;函式reverse將連結串列head逆置,並返回結果連結串列的頭指標。

裁判測試程式樣例:

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

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

struct ListNode *createlist(); /*裁判實現,細節不表*/
struct ListNode *reverse( struct ListNode *head );
void printlist( struct ListNode *head )
{
     struct ListNode *p = head;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode  *head;

    head = createlist();
    head = reverse(head);
    printlist(head);

    return 0;
}

/* 你的程式碼將被嵌在這裡 */

輸入樣例:

1 2 3 4 5 6 -1

輸出樣例:

6 5 4 3 2 1

在只有尾指標的情況下完成倒序。有點燒腦,理清之後很簡單

配合如下圖解食用:

這只是前兩次逆置的實現,後續同理。

struct ListNode *reverse( struct ListNode *head )
{struct ListNode *q;
    struct ListNode *s;
    struct ListNode *s1=NULL;
    q=head;
    for(;q!=NULL;)
    {   s=(struct ListNode *)malloc(sizeof(struct ListNode *));
         s->data=q->data;
         s->next=s1;
         s1=s;
         q=q->next;
    }
    return s1;

};

03帶頭結點的單鏈表就地逆置

本題要求編寫函式實現帶頭結點的單鏈線性表的就地逆置操作函式。

L是一個帶頭結點的單鏈表,函式ListReverse_L(LinkList &L)要求在不新開闢節點的前提下將單鏈表中的元素進行逆置,如原單鏈表元素依次為1,2,3,4,則逆置後為4,3,2,1。

函式介面定義:

void ListReverse_L(LinkList &L);

其中L是一個帶頭結點的單鏈表。

裁判測試程式樣例:

//庫函式標頭檔案包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
 
//函式狀態碼定義
#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE -1
#define OVERFLOW   -2
 
typedef int  Status;
typedef int  ElemType; //假設線性表中的元素均為整型
 
typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;
 
Status ListCreate_L(LinkList &L,int n)
{
    LNode *rearPtr,*curPtr;   //一個尾指標,一個指向新節點的指標
    L=(LNode*)malloc(sizeof (LNode));
    if(!L)exit(OVERFLOW);
    L->next=NULL;               //先建立一個帶頭結點的單鏈表
    rearPtr=L;  //初始時頭結點為尾節點,rearPtr指向尾巴節點
    for (int i=1;i<=n;i++){  //每次迴圈都開闢一個新節點,並把新節點拼到尾節點後
        curPtr=(LNode*)malloc(sizeof(LNode));//生成新結點
        if(!curPtr)exit(OVERFLOW);
        scanf("%d",&curPtr->data);//輸入元素值
        curPtr->next=NULL;  //最後一個節點的next賦空
        rearPtr->next=curPtr;
        rearPtr=curPtr;
    }
    return OK;
}
void ListReverse_L(LinkList &L);
void ListPrint_L(LinkList &L){
//輸出單鏈表
    LNode *p=L->next;  //p指向第一個元素結點
    while(p!=NULL)
    {
          if(p->next!=NULL)
               printf("%d ",p->data);
          else
               printf("%d",p->data);
          p=p->next;
    }
}
int main()
{
    LinkList L;
    int n;
    scanf("%d",&n);
    if(ListCreate_L(L,n)!= OK) {
          printf("表建立失敗!!!\n");
          return -1;
    }
    ListReverse_L(L);
    ListPrint_L(L);
    return 0;
}
/* 請在這裡填寫答案 */

輸入格式

第一行輸入一個整數n,表示單鏈表中元素個數,接下來一行共n個整數,中間用空格隔開。

輸出格式

輸出逆置後順序表的各個元素,兩個元素之間用空格隔開,最後一個元素後面沒有空格。

輸入樣例:

4

1 2 3 4

輸出樣例:

4 3 2 1

注意兩點,一個是題面中所說的”要求在不新開闢節點的前提下“,一個是要將L本身逆置,不是逆置入新連結串列

void ListReverse_L(LinkList &L)//L為頭結點
{
    LinkList p,q;
    p = L->next;
    L->next = NULL;
    while(p)
    {
        //向後挪
        q = p;//
        p = p->next;
        //頭插
        q->next = L->next;//非常重要,相當於p和q之間沒有了指標連線
        //q->next=NULL;
        L->next = q;//把q接到頭的後面
    }
}
void ListReverse_L(LinkList &L)//L為頭結點
{
    LinkList p,q;
    p = L->next;
    L->next = NULL;
    while(p)
    {   
q=p; q->next=L->next; L->next=q; p=p->next; } }


04刪除單鏈表中最後一個與給定值相等的結點#

本題要求在連結串列中刪除最後一個數據域取值為x的節點。L是一個帶頭結點的單鏈表,函式ListLocateAndDel_L(LinkList L, ElemType x)要求在連結串列中查詢最後一個數據域取值為x的節點並將其刪除。例如,原單鏈表各個節點的資料域依次為1 3 1 4 3 5,則ListLocateAndDel_L(L,3)執行後,連結串列中剩餘各個節點的資料域取值依次為1 3 1 4 5。

函式介面定義:

void ListLocateAndDel_L(LinkList L, ElemType x);

其中 L 是一個帶頭節點的單鏈表。 x 是一個給定的值。函式須在連結串列中定位最後一個數據域取值為x的節點並刪除之。

裁判測試程式樣例:

//庫函式標頭檔案包含
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//函式狀態碼定義
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define NULL 0

typedef int Status;
typedef int ElemType; //假設線性表中的元素均為整型

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;

//連結串列建立函式
Status ListCreate_L(LinkList &L, int n)
{
    LNode *rearPtr, *curPtr;
    L = (LNode *)malloc(sizeof(LNode));
    if (!L)
        exit(OVERFLOW);
    L->next = NULL;
    rearPtr = L;
    for (int i = 1; i <= n; i++)
    {
        curPtr = (LNode *)malloc(sizeof(LNode));
        if (!curPtr)
            exit(OVERFLOW);
        scanf("%d", &curPtr->data);
        curPtr->next = NULL;
        rearPtr->next = curPtr;
        rearPtr = curPtr;
    }
    return OK;
}

//連結串列輸出函式
void ListPrint_L(LinkList L)
{
    LNode *p = L->next;
    if (!p)
    {
        printf("空表");
        return;
    }
    while (p != NULL)
    {
        if (p->next != NULL)
            printf("%d ", p->data);
        else
            printf("%d", p->data);
        p = p->next;
    }
}

//下面是需要實現的函式的宣告
void ListLocateAndDel_L(LinkList L, ElemType x);

int main()
{
    LinkList L;
    int n;
    int x;
    scanf("%d", &n);
    //輸入連結串列中元素個數

    if (ListCreate_L(L, n) != OK)
    {
        printf("表建立失敗!!!\n");
        return -1;
    }
    scanf("%d", &x); //輸入待查詢元素
    ListLocateAndDel_L(L, x);
    ListPrint_L(L);
    return 0;
}
/* 請在這裡填寫答案 */

輸入樣例:

6
1 3 1 4 3 5
3

輸出樣例:

1 3 1 4 5

答案:

void ListLocateAndDel_L(LinkList L, ElemType x)
{
    if(!L)
        return;//表空啥也不幹
    else
    {
        LinkList p = L->next,q,t=L;//t指向頭結點
        while(p)
        {
            if(p->data==x)
                t = q;//記錄並更新相同位置(t也是要刪除位置的直接前驅)
            q = p;//這兩部就是不等就一直往後更新
            p = p->next;
        }
        if(t!=L)//大概的意思就是t往後移動了,就可以刪了(不知道不寫這句行不行)
        {
            t->next = t->next->next;//刪除操作
        }
    }
}

另一個方法:

void ListLocateAndDel_L(LinkList L, ElemType x);
{
    if(L->next==NULL)
        return ;
    else
    {
        LNode *p=L->next;
        LNode *q;
        int count=0;
        int recount=0;
        while(p)
        {
            if(p->data==x)
                count++;
            p=p->next;
        }
        while(L)
        {
            if(p->data==x)
            {
                recount++;
                if(recount==count)
                {
                    q=L->next;
                    L->next=L->next->next;
                    free(q);
                }
            }
            L=L->next;
        }
    }
}

05另類堆疊

在棧的順序儲存實現中,另有一種方法是將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 

注意Data是個陣列!!!

bool Push( Stack S, ElementType X )
{
    if(S->Top==S->MaxSize)
    {
        printf("Stack Full\n");
        return false;
    }
    else 
    {
        S->Data[(S->Top)]=X;
        S->Top++;
        return true;
    }
}
ElementType Pop( Stack S )
{
    if(S->Top==0)
    {
        printf("Stack Empty\n");
        return ERROR;
    }
    else return S->Data[--(S->Top)];
}


06在一個數組中實現兩個堆疊

本題要求在一個數組中實現兩個堆疊。

函式介面定義:

Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag );

其中Tag是堆疊編號,取1或2;MaxSize堆疊陣列的規模;Stack結構定義如下:

typedef int Position;
struct SNode {
    ElementType *Data;
    Position Top1, Top2;
    int MaxSize;
};
typedef struct SNode *Stack;

注意:如果堆疊已滿,Push函式必須輸出“Stack Full”並且返回false;如果某堆疊是空的,則Pop函式必須輸出“Stack Tag Empty”(其中Tag是該堆疊的編號),並且返回ERROR。

裁判測試程式樣例:

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

#define ERROR 1e8
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
struct SNode {
    ElementType *Data;
    Position Top1, Top2;
    int MaxSize;
};
typedef struct SNode *Stack;

Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag );

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

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

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

/* 你的程式碼將被嵌在這裡 */

輸入樣例:

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

輸出樣例:

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

分析:

題目要求三個函式,建棧、入棧、出棧.

“在一個數組中實現兩個堆疊”是指可以雙向出入。我們來分析樣例:

定義大小為5的棧

Push 1 1      頂入1
Pop 2         尾出元素,失敗,報錯
Push 2 11     尾入11
Push 1 2      頂入2
Push 2 12     尾入12
Pop 1         頂出元素,出2
Push 2 13     尾入13
Push 2 14     尾入14
Push 1 3      頂入3,失敗,報錯
Pop 2         尾出元素,出14
Stack CreateStack( int MaxSize )
{
    struct SNode *S=NULL;
    S=(struct SNode *)malloc(sizeof(struct SNode));
    S->Data=(int *)malloc(MaxSize*sizeof(int));
    S->Top1=-1;
    S->Top2=MaxSize;
    S->MaxSize=MaxSize;
    return S;
}
bool Push( Stack S, ElementType X, int Tag )
{
    if(S->Top2-S->Top1==1)
    {
        printf("Stack Full\n");
        return false;
    }
    else
    {
        if(Tag==1)
            S->Data[++(S->Top1)]=X;
        else if(Tag==2)
            S->Data[--(S->Top2)]=X;
        return true;
    }
}
ElementType Pop( Stack S, int Tag )
{
    if(Tag==1)
    {
        if(S->Top1==-1)
        {
            printf("Stack %d Empty\n",Tag);
            return ERROR;
        }
        else
            return S->Data[(S->Top1)--];
    }
    else if(Tag==2)
    {
        if(S->Top2==S->MaxSize)
        {
            printf("Stack %d Empty\n",Tag);
            return ERROR;
        }
        else
        {
            return S->Data[(S->Top2)++];
        }
    }
}

07先序輸出葉子結點

本題要求按照先序遍歷的順序輸出給定二叉樹的葉結點。

函式介面定義:

void PreorderPrintLeaves( BinTree BT );

其中BinTree結構定義如下:

typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

函式PreorderPrintLeaves應按照先序遍歷的順序輸出給定二叉樹BT的葉結點,格式為一個空格跟著一個字元。

裁判測試程式樣例:

#include <stdio.h>
#include <stdlib.h>
 
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};
 
BinTree CreatBinTree(); /* 實現細節忽略 */
void PreorderPrintLeaves( BinTree BT );
 
int main()
{
    BinTree BT = CreatBinTree();
    printf("Leaf nodes are:");
    PreorderPrintLeaves(BT);
    printf("\n");
 
    return 0;
}
/* 你的程式碼將被嵌在這裡 */

輸出樣例:

Leaf nodes are: D E H I

void PreorderPrintLeaves( BinTree BT )
{
    if(BT)
    {
        if(BT->Left==MULL&&BT->Right==NULL)
            printf("%c ",BT->Data);
        else
        {
            if(BT->Left)
            {
                PreorderPrintLeaves(BT->Data);
            }
            if(BT->Right)
            {
                PreorderPrintLeaves(BT->Data);
            }
        }
    }
}
void PreorderPrintLeaves( BinTree BT )
{
    if(BT)
    {
        if(!BT->Left&&!BT->Right)
            printf(" %c",BT->Data);
        PreorderPrintLeaves(BT->Left);
        PreorderPrintLeaves(BT->Right);
    }
    return;
}

08二叉樹的遍歷

6-2 二叉樹的遍歷 (25分)

本題要求給定二叉樹的4種遍歷。

函式介面定義:

void InorderTraversal( BinTree BT );
void PreorderTraversal( BinTree BT );
void PostorderTraversal( BinTree BT );
void LevelorderTraversal( BinTree BT );

其中BinTree結構定義如下:

typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

要求4個函式分別按照訪問順序打印出結點的內容,格式為一個空格跟著一個字元。

裁判測試程式樣例:

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

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

BinTree CreatBinTree(); /* 實現細節忽略 */
void InorderTraversal( BinTree BT );
void PreorderTraversal( BinTree BT );
void PostorderTraversal( BinTree BT );
void LevelorderTraversal( BinTree BT );

int main()
{
    BinTree BT = CreatBinTree();
    printf("Inorder:");    InorderTraversal(BT);    printf("\n");
    printf("Preorder:");   PreorderTraversal(BT);   printf("\n");
    printf("Postorder:");  PostorderTraversal(BT);  printf("\n");
    printf("Levelorder:"); LevelorderTraversal(BT); printf("\n");
    return 0;
}
/* 你的程式碼將被嵌在這裡 */

輸出樣例(對於圖中給出的樹):

Inorder: D B E F A G H C I
Preorder: A B D F E C G H I
Postorder: D E F B H G I C A
Levelorder: A B C D F G I E H
void InorderTraversal( BinTree BT )//中序遍歷
{
    if(BT)
    {
        if(BT->Left)
            InorderTraversal(BT->Left);
        printf(" %c",BT->Data);
        if(BT->Right)
            InorderTraversal(BT->Right);
    }
}
void PreorderTraversal( BinTree BT )//前序遍歷
{
    if(BT)
    {
        printf(" %c",BT->Data);
        if(BT->Left)
            PreorderTraversal(BT->Left);
        if(BT->Right)
            PreorderTraversal(BT->Right);
    }
}
void PostorderTraversal( BinTree BT )//後序遍歷
{
    if(BT)
    {
        if(BT->Left)
            PostorderTraversal(BT->Left);
        if(BT->Right)
            PostorderTraversal(BT->Right);
        printf(" %c",BT->Data);
    }
}
void LevelorderTraversal( BinTree BT )//逐層遍歷
{
    if(!BT)
        return;
    BinTree a[10000],b;
    a[0]=BT;
    int len=1;//len記錄當前層的節點數量
    while(1)
    {
        if(len==0)
            return;
        int pos=0;
        BinTree b[10000];

        for(int i=0; i<len; i++)
        {
            if(a[i]!=NULL)
                printf(" %c",a[i]->Data);
            if(a[i]->Left!=NULL)
                b[pos++]=a[i]->Left;
            if(a[i]->Right!=NULL)
                b[pos++]=a[i]->Right;
        }

        len=pos;//更新下一層寬度,為下一次迴圈做準備
        for(int i=0; i<len; i++) //將下層的b賦給a,為下一次迴圈做準備
            a[i]=b[i];
    }
}

09求二叉樹高度

本題要求給定二叉樹的高度。

函式介面定義:

int GetHeight( BinTree BT );

其中BinTree結構定義如下:

typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

要求函式返回給定二叉樹BT的高度值。

裁判測試程式樣例:

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

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

BinTree CreatBinTree(); /* 實現細節忽略 */
int GetHeight( BinTree BT );

int main()
{
    BinTree BT = CreatBinTree();
    printf("%d\n", GetHeight(BT));
    return 0;
}
/* 你的程式碼將被嵌在這裡 */

輸出樣例(對於圖中給出的樹):

4
int GetHeight(BinTree BT)
{
    int lh,rh;
    if(BT==NULL)
        return 0;
    else
    {
        lh=GetHeight(BT->Left);
        rh=GetHeight(BT->Right);
        return lh>rh?++lh:++rh;
    }//else
}

10查詢子串

本題要求實現一個字串查詢的簡單函式。

函式介面定義:

char *search( char *s, char *t );

函式search在字串s中查詢子串t,返回子串t在s中的首地址。若未找到,則返回NULL。

裁判測試程式樣例:

#include <stdio.h>
#define MAXS 30

char *search(char *s, char *t);
void ReadString( char s[] ); /* 裁判提供,細節不表 */

int main()
{
    char s[MAXS], t[MAXS], *pos;

    ReadString(s);
    ReadString(t);
    pos = search(s, t);
    if ( pos != NULL )
        printf("%d\n", pos - s);
    else
        printf("-1\n");

    return 0;
}

/* 你的程式碼將被嵌在這裡 */

輸入樣例1:

The C Programming Language
ram

輸出樣例1:

10

輸入樣例2:

The C Programming Language
bored

輸出樣例2:

-1

char *search(char *s, char *t)
{
    int i = 0;
    int len1=strlen(s);
    int len2=strlen(t);
    while (i<len1)
    {
        if (s[i] == t[0])
        {
            int j = 1;
            while (s[i + j] == t[j] && j<len2)
            {
                j++;
            }
            if (t[j] == '\0')
            {
               return s+i;
            }
        }//if
        i++;
    }//while
    return NULL;
}

11線性探測法的查詢函式

函式介面定義:

Position Find( HashTable H, ElementType Key );

其中HashTable是開放地址散列表,定義如下:

#define MAXTABLESIZE 100000  /* 允許開闢的最大散列表長度 */
typedef int ElementType;     /* 關鍵詞型別用整型 */
typedef int Index;           /* 雜湊地址型別 */
typedef Index Position;      /* 資料所在位置與雜湊地址是同一型別 */
/* 雜湊單元狀態型別,分別對應:有合法元素、空單元、有已刪除元素 */
typedef enum { Legitimate, Empty, Deleted } EntryType;

typedef struct HashEntry Cell; /* 散列表單元型別 */
struct HashEntry{
    ElementType Data; /* 存放元素 */
    EntryType Info;   /* 單元狀態 */
};

typedef struct TblNode *HashTable; /* 散列表型別 */
struct TblNode {   /* 散列表結點定義 */
    int TableSize; /* 表的最大長度 */
    Cell *Cells;   /* 存放雜湊單元資料的陣列 */
};

函式Find應根據裁判定義的雜湊函式Hash( Key, H->TableSize )從散列表H中查到Key的位置並返回。如果Key不存在,則返回線性探測法找到的第一個空單元的位置;若沒有空單元,則返回ERROR

裁判測試程式樣例:

#include <stdio.h>

#define MAXTABLESIZE 100000  /* 允許開闢的最大散列表長度 */
typedef int ElementType;     /* 關鍵詞型別用整型 */
typedef int Index;           /* 雜湊地址型別 */
typedef Index Position;      /* 資料所在位置與雜湊地址是同一型別 */
/* 雜湊單元狀態型別,分別對應:有合法元素、空單元、有已刪除元素 */
typedef enum { Legitimate, Empty, Deleted } EntryType;

typedef struct HashEntry Cell; /* 散列表單元型別 */
struct HashEntry{
    ElementType Data; /* 存放元素 */
    EntryType Info;   /* 單元狀態 */
};

typedef struct TblNode *HashTable; /* 散列表型別 */
struct TblNode {   /* 散列表結點定義 */
    int TableSize; /* 表的最大長度 */
    Cell *Cells;   /* 存放雜湊單元資料的陣列 */
};

HashTable BuildTable(); /* 裁判實現,細節不表 */
Position Hash( ElementType Key, int TableSize )
{
    return (Key % TableSize);
}

#define ERROR -1
Position Find( HashTable H, ElementType Key );

int main()
{
    HashTable H;
    ElementType Key;
    Position P;

    H = BuildTable(); 
    scanf("%d", &Key);
    P = Find(H, Key);
    if (P==ERROR)
        printf("ERROR: %d is not found and the table is full.\n", Key);
    else if (H->Cells[P].Info == Legitimate)
        printf("%d is at position %d.\n", Key, P);
    else
        printf("%d is not found.  Position %d is returned.\n", Key, P);

    return 0;
}

/* 你的程式碼將被嵌在這裡 */

輸入樣例1:(注:-1表示該位置為空。下同。)

11
11 88 21 -1 -1 5 16 7 6 38 10
38

輸出樣例1:

38 is at position 9.

輸入樣例2:

11
11 88 21 -1 -1 5 16 7 6 38 10
41

輸出樣例2:

41 is not found.  Position 3 is returned.

輸入樣例3:

11
11 88 21 3 14 5 16 7 6 38 10
41

輸出樣例3:

ERROR: 41 is not found and the table is full.

分析:注意題幹中這句話即可:根據裁判定義的雜湊函式Hash( Key, H->TableSize )從散列表H中查到Key的位置並返回

Position Find( HashTable H, ElementType Key )
{
    int flag=0;
    Position p,q;
    p=Hash(Key,H->TableSize);
    q=Hash(Key,H->TableSize);
    while(H->Cells[p].Data!=Key&&H->Cells[p].Info!=Empty)
    {
        flag++;
        if(flag==MAXTABLESIZE)
        {
            return ERROR;
        }
        p=(q+flag)%H->TableSize;
    }
    return p;
}