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
X
在Data
中的位置,即陣列下標(注意:元素從下標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;
}