数据结构PTA
作业1:线性表的顺序存储
6-1 数组元素的区间删除 (40 分)
给定一个顺序存储的线性表,请设计一个函数删除所有值大于min而且小于max的元素。删除后表中剩余元素保持顺序存储,并且相对位置不能改变。
函数接口定义:
int Delete( int A[], int L, int minA, int maxA );
其中A
是整型数组,存储原始线性表的元素;L
是表长,即A
中元素的个数;minA
和maxA
分别为待删除元素的值域的下、上界。函数Delete
应将A
中所有值大于minA
而且小于maxA
的元素删除,同时保证表中剩余元素保持顺序存储,并且相对位置不变,最后返回删除后的表长。
裁判测试程序样例:
#include <stdio.h>
#define MAXN 20
int Delete( int A[], int L, int minA, int maxA );
int main()
{
int A[MAXN], L, minA, maxA, i;
scanf("%d", &L);
for (i=0; i<L; i++) scanf("%d", &A[i]);
scanf("%d %d", &minA, &maxA);
L = Delete(A, L, minA, maxA);
for (i=0; i<L; i++) printf("%d ", A[i]);
printf("\n");
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
10
4 -8 2 12 1 5 9 3 3 10
0 4
输出样例:
4 -8 12 5 9 10
int Delete(int A[], int L, int minA, int maxA) {
int i=0,j=0,b[MAXN];
for (i = 0; i < L; i++) {
if (A[i] <= minA || A[i] >= maxA)
b[j++]=A[i];
}
for(i=0;i<j;i++)
A[i]=b[i];
L=j;
return L;
}
本题要求实现顺序表的操作集。
函数接口定义:
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
其中List
结构定义如下:
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
各个操作函数的定义为:
List MakeEmpty()
:创建并返回一个空的线性表;
Position Find( List L, ElementType X )
:返回线性表中X的位置。若找不到则返回ERROR;
bool Insert( List L, ElementType X, Position P )
:将X插入在位置P并返回true。若空间已满,则打印“FULL”并返回false;如果参数P指向非法位置,则打印“ILLEGAL POSITION”并返回false;
bool Delete( List L, Position P )
:将位置P的元素删除并返回true。若参数P指向非法位置,则打印“POSITION P EMPTY”(其中P是参数值)并返回false。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 5
#define ERROR -1
typedef enum {false, true} bool;
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
int main()
{
List L;
ElementType X;
Position P;
int N;
L = MakeEmpty();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
if ( Insert(L, X, 0)==false )
printf(" Insertion Error: %d is not in.\n", X);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else
printf("%d is at position %d.\n", X, P);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &P);
if ( Delete(L, P)==false )
printf(" Deletion Error.\n");
if ( Insert(L, 0, P)==false )
printf(" Insertion Error: 0 is not in.\n");
}
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
6
1 2 3 4 5 6
3
6 5 1
2
-1 6
输出样例:
FULL Insertion Error: 6 is not in.
Finding Error: 6 is not in.
5 is at position 0.
1 is at position 4.
POSITION -1 EMPTY Deletion Error.
FULL Insertion Error: 0 is not in.
POSITION 6 EMPTY Deletion Error.
FULL Insertion Error: 0 is not in.
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 5
#define ERROR -1
typedef enum {false, true} bool;
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
int main()
{
List L;
ElementType X;
Position P;
int N;
L = MakeEmpty();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
if ( Insert(L, X, 0)==false )
printf(" Insertion Error: %d is not in.\n", X);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else
printf("%d is at position %d.\n", X, P);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &P);
if ( Delete(L, P)==false )
printf(" Deletion Error.\n");
if ( Insert(L, 0, P)==false )
printf(" Insertion Error: 0 is not in.\n");
}
return 0;
}
/* 你的代码将被嵌在这里 */
List MakeEmpty() {
List l;
l = (List)malloc(sizeof(struct LNode));
l->Last = ERROR;
return l;
}
Position Find(List L, ElementType X) {
int i;
for (i = 0; i < MAXSIZE; i++) {
if (L->Data[i] == X)
return i;
}
return ERROR;
}
bool Insert(List L, ElementType X, Position P) {
int i;
if (L->Last==MAXSIZE-1) {
printf("FULL");
return false;
}
if (P < 0 || P > L->Last + 1)
{
printf("ILLEGAL POSITION");
return false;
}
for (i = P; i < L->Last+1; i++) {
L->Data[i + 1] = L->Data[i];
}
L->Data[P] = X;
L->Last++;
return true;
}
bool Delete(List L, Position P) {
if (P < 0 || P > L->Last)
{
printf("POSITION %d EMPTY", P);
return false;
}
for(int i=P;i<L->Last;i++)
L->Data[i] = L->Data[i+1];
L->Last--;
return true;
}
作业2:线性表的链式存储
本题要求实现一个函数,求链式表的表长。
函数接口定义:
int Length( List L );
其中List
结构定义如下:
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode List;
L
是给定单链表,函数Length
要返回链式表的长度。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode List;
List Read(); /* 细节在此不表 */
int Length( List L );
int main()
{
List L = Read();
printf("%d\n", Length(L));
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
1 3 4 5 2 -1
输出样例:
5
int Length( List L ){
int i=0;
while(L){
i++;
L=L->Next;
}
return i;
}
本题要求实现带头结点的链式表操作集。
函数接口定义:
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
其中List
结构定义如下:
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
各个操作函数的定义为:
List MakeEmpty()
:创建并返回一个空的线性表;
Position Find( List L, ElementType X )
:返回线性表中X的位置。若找不到则返回ERROR;
bool Insert( List L, ElementType X, Position P )
:将X插入在位置P指向的结点之前,返回true。如果参数P指向非法位置,则打印“Wrong Position for Insertion”,返回false;
bool Delete( List L, Position P )
:将位置P的元素删除并返回true。若参数P指向非法位置,则打印“Wrong Position for Deletion”并返回false。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
#define ERROR NULL
typedef enum {false, true} bool;
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
int main()
{
List L;
ElementType X;
Position P;
int N;
bool flag;
L = MakeEmpty();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
flag = Insert(L, X, L->Next);
if ( flag==false ) printf("Wrong Answer\n");
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else {
flag = Delete(L, P);
printf("%d is found and deleted.\n", X);
if ( flag==false )
printf("Wrong Answer.\n");
}
}
flag = Insert(L, X, NULL);
if ( flag==false ) printf("Wrong Answer\n");
else
printf("%d is inserted as the last element.\n", X);
P = (Position)malloc(sizeof(struct LNode));
flag = Insert(L, X, P);
if ( flag==true ) printf("Wrong Answer\n");
flag = Delete(L, P);
if ( flag==true ) printf("Wrong Answer\n");
for ( P=L->Next; P; P = P->Next ) printf("%d ", P->Data);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
6
12 2 4 87 10 2
4
2 12 87 5
输出样例:
2 is found and deleted.
12 is found and deleted.
87 is found and deleted.
Finding Error: 5 is not in.
5 is inserted as the last element.
Wrong Position for Insertion
Wrong Position for Deletion
10 4 2 5
#include <stdio.h>
#include <stdlib.h>
#define ERROR NULL
typedef enum { false, true } bool;
typedef int ElementType;
typedef struct LNode* PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
List MakeEmpty();
Position Find(List L, ElementType X);
bool Insert(List L, ElementType X, Position P);
bool Delete(List L, Position P);
int main()
{
List L;
ElementType X;
Position P;
int N;
bool flag;
L = MakeEmpty();
scanf_s("%d", &N);
while (N--) {
scanf_s("%d", &X);
flag = Insert(L, X, L->Next);
if (flag == false) printf("Wrong Answer\n");
}
scanf_s("%d", &N);
while (N--) {
scanf_s("%d", &X);
P = Find(L, X);
if (P == ERROR)
printf("Finding Error: %d is not in.\n", X);
else {
flag = Delete(L, P);
printf("%d is found and deleted.\n", X);
if (flag == false)
printf("Wrong Answer.\n");
}
}
flag = Insert(L, X, NULL);
if (flag == false) printf("Wrong Answer\n");
else
printf("%d is inserted as the last element.\n", X);
P = (Position)malloc(sizeof(struct LNode));
flag = Insert(L, X, P);
if (flag == true) printf("Wrong Answer\n");
flag = Delete(L, P);
if (flag == true) printf("Wrong Answer\n");
for (P = L->Next; P; P = P->Next) printf("%d ", P->Data);
return 0;
}
List MakeEmpty() {
List Head = (List)malloc(sizeof(struct LNode));
Head->Next = NULL;
return Head;
}
Position Find(List L, ElementType X) {
List P = L->Next;
while (P != NULL) {
if (P->Data == X) return P;
P = P->Next;
}
return ERROR;
}
bool Insert(List L, ElementType X, Position P) {
List pa = L;
while (pa != NULL && pa->Next != P)
pa = pa->Next;
if (pa == NULL) {
printf("%s\n", "Wrong Position for Insertion");
return false;
}
List pb= (List)malloc(sizeof(struct LNode));
pb->Data = X;
pb->Next = P;
pa->Next = pb;
return true;
}
bool Delete(List L, Position P) {
List pa = L;
while (pa != NULL && pa->Next != P)
pa = pa->Next;
if (pa == NULL) {
printf("%s\n", "Wrong Position for Deletion");
return false;
}
pa->Next = P->Next;
return true;
}
作业3:
6-1 带头结点链栈的操作 (20 分)
本题要求实现带头链表的栈,写出Push 、Pop函数。
函数接口定义:
Status Push(LinkList L,ElemType e);
Status Pop(LinkList L,ElemType *e);
其中 L
和 e
都是用户传入的参数。 L
是带头结点的头指针; e
是数据元素。 其中 LinkList
定义如下:
typedef struct LNode
{
ElemType data;
struct LNode * next;
}LNode,*LinkList;
裁判测试程序样例:
#include <malloc.h>
#include <stdio.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode * next;
}LNode,*LinkList;
Status InitList(LinkList *L);
Status List(LinkList L);
Status ListInsert(LinkList L,int i,ElemType e);
int main()
{
LinkList L;
int x;
InitList(&L);
Push(L,1);Push(L,2);Push(L,3);
List(L);
Pop(L,&x);
printf(" %d\n",x);
List(L);
return 0;
}
/* 请在这里填写答案 */
输出样例:
在这里给出相应的输出。例如:
3 2 1
3
2 1
Status Push(LinkList L,ElemType e){
LinkList p= (LinkList)malloc(sizeof(struct LNode)); //生成新结点p
p->data=e;
p->next=L->next;
L->next=p;
return e;
}
Status Pop(LinkList L,ElemType *e){
if (L->next==NULL)
return ERROR;
*e = L->next-> data;
L ->next= L-> next->next;
return *e;
}
6-2 带头结点的链队列的基本操作 (20 分)
实现链队列的入队列及出队列操作。
函数接口定义:
Status QueueInsert(LinkQueue *Q,ElemType e);
Status QueueDelete(LinkQueue *Q,ElemType *e);
其中 Q
和 e
都是用户传入的参数。 LinkQueue
的类型定义如下:
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode * next;
}LNode,*LinkList;
typedef struct
{
LinkList front,rear; /* 队头、队尾指针 */
}LinkQueue;
裁判测试程序样例:
#include <stdio.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode * next;
}LNode,*LinkList;
typedef struct
{
LinkList front,rear; /* 队头、队尾指针 */
}LinkQueue;
/* 带头结点的链队列的基本操作 */
Status InitQueue(LinkQueue *Q)
{ /* 构造一个空队列Q */
LinkList p;
p=(LNode*)malloc(sizeof(LNode));
p->next=NULL;
(*Q).rear=(*Q).front=p;
return OK;
}
Status List(LinkList L)
{
LinkList p;
if(!L) return ERROR;
p=L->next;
while(p)
{
printf(" %d",p->data);
p=p->next;
}
printf("\n");
return OK;
}
int QueueLenth(LinkQueue Q)
{
int n=0;
LinkList p;
if(Q.rear==Q.front)
return 0;
p=Q.front->next;
while(p)
{
n++;
p=p->next;
}
return n;
}
int main()
{
int x;
LinkQueue Q;
InitQueue(&Q);
QueueInsert(&Q,1);QueueInsert(&Q,2);QueueInsert(&Q,3);
List(Q.front );
QueueDelete( &Q,&x);
printf(" %d %d\n",x,QueueLenth(Q));
QueueDelete(&Q,&x);QueueDelete(&Q,&x);
printf(" %d %d\n",x,QueueLenth(Q));
return 0;
}
/* 请在这里填写答案 */
输出样例:
在这里给出相应的输出。例如:
1 2 3
1 2
3 0
C代码
Status QueueInsert(LinkQueue *Q,ElemType e){
LinkList p=(LinkList)malloc(sizeof(struct LNode));
if(p==NULL)
return ERROR;
p->data=e;
p->next=NULL;
Q->rear->next=p;
Q->rear=p;
return OK;
}
Status QueueDelete(LinkQueue *Q,ElemType *e){
LNode *p;
p=Q->front->next;
if(Q->front==Q->rear)
{
return ERROR;
}
Q->front->next=p->next;
if(Q->rear==p) Q->rear=Q->front;
*e=p->data;
free(p);
return OK;
}
7-1 一元多项式的乘法与加法运算 (60 分)
设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0
。
输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
输出样例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0
#include<stdio.h>
int main(){
int a[2][1000],b[2][1000],c[2][10000]={0},d[10000]={0},h[10000]={0},add[2][1000],mut[2][1000];
int m,n,k,k1;
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d %d",&a[0][i],&a[1][i]);
d[a[1][i]]+=a[0][i];
}
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d %d",&b[0][i],&b[1][i]);
d[b[1][i]]+=b[0][i];
}
k=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
c[0][k]=a[0][i]*b[0][j];
c[1][k]=a[1][i]+b[1][j];
h[c[1][k]]+=c[0][k];
k++;
}
}
k1=0;
for(int i=2000;i>=0;i--){
if(h[i]!=0){
mut[0][k1]=h[i];
mut[1][k1]=i;
k1++;
}
}
for(int i=0;i<k1;i++){
printf("%d %d",mut[0][i],mut[1][i]);
if(i<k1-1)
printf(" ");
}
if(k1==0)
{
printf("0 0");
}
printf("\n");
k1=0;
for(int i=2000;i>=0;i--){
if(d[i]!=0){
add[0][k1]=d[i];
add[1][k1]=i;
k1++;
}
}
for(int i=0;i<k1;i++){
printf("%d %d",add[0][i],add[1][i]);
if(i<k1-1)
printf(" ");
}
if(k1==0)
{
printf("0 0");
}
}
只有一个队尾指针的循环队列
//_DataStructure_C_Impl:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef char DataType;
typedef struct snode{ //链式堆栈结点类型定义
DataType data;
struct snode *next;
}LSNode;
typedef struct QNode{ //只有队尾指针的链式循环队列类型定义
DataType data;
struct QNode *next;
}LQNode,*LinkQueue;
//带头结点的链式堆栈初始化
void InitStack(LSNode **head){
if((*head=(LSNode *)malloc(sizeof(LSNode)))==NULL){
printf("分配结点不成功");
exit(-1);
}else{
(*head)->next=NULL;
}
}
//判断带头结点链式堆栈是否为空。如果堆栈为空,返回1,否则返回0
int StackEmpty(LSNode *head){
if(head->next==NULL)
return 1;
else
return 0;
}
//链式堆栈进栈。进栈成功返回1,否则退出
int PushStack(LSNode *head,DataType e){
LSNode *s;
if((s=(LSNode *)malloc(sizeof(LSNode)))==NULL) //为结点分配空间,失败退出程序并返回-1
exit(-1);
else{
s->data=e; //把元素值赋值给结点的数据域
s->next=head->next; //将结点插入到栈顶
head->next=s;
return 1;
}
}
//链式堆栈出栈,需要判断堆栈是否为空。出栈成功返回1,否则返回0
int PopStack(LSNode *head,DataType *e){
LSNode *s=(LSNode *)malloc(sizeof(LSNode));
if(!s) exit(-1);
s=head->next; //指针s指向栈顶结点
if(StackEmpty(head)) //判断堆栈是否为空
return 0;
else{
head->next=s->next; //头结点的指针指向第二个结点位置
*e=s->data; //要出栈的结点元素赋值给e
free(s); //释放要出栈的结点空间
return 1;
}
}
//将带头结点的链式循环队列初始化为空队列,需要把头结点的指针指向头结点
void InitQueue(LinkQueue *rear){
if((*rear=(LQNode*)malloc(sizeof(LQNode)))==NULL)
exit(-1); //如果申请结点空间失败退出
else
(*rear)->next=*rear; //队尾指针指向头结点
}
//判断链式队列是否为空,队列为空返回1,否则返回0
int QueueEmpty(LinkQueue rear){
if(rear->next==rear)
return 1;
else
return 0;
}
//将元素e插入到链式队列中,插入成功返回1
int EnterQueue(LinkQueue *rear,DataType e){
LQNode *s;
s=(LQNode *)malloc(sizeof(LQNode)); //为将要入队的元素申请一个结点的空间
if(!s)
exit(-1);
s->data=e; //将元素值赋值给结点的数据域
s->next=(*rear)->next; //将新结点插入链式队列
(*rear)->next=s;
*rear=s; //修改队尾指针
return 1;
}
//删除链式队列中的队头元素,并将该元素赋值给e,删除成功返回1,否则返回0
int DeleteQueue(LinkQueue *rear,DataType *e){
LQNode *f,*p;
if(*rear==(*rear)->next) //在删除队头元素即出队列之前,判断链式队列是否为空
return 0;
else{
f=(*rear)->next; //使指针f指向头结点
p=f->next; //使指针p指向要删除的结点
if(p==*rear){ //处理队列中只有一个结点的情况
*rear=(*rear)->next; //使指针rear指向头结点
(*rear)->next=*rear;
}else{
f->next=p->next; //使头结点指向要出队列的下一个结点
}
*e=p->data; //把队头元素值赋值给e
free(p); //释放指针p指向的结点
return 1;
}
}
void main(){
LinkQueue LQueue1,LQueue2; /*定义链式循环队列*/
LSNode *LStack1,*LStack2; /*定义链式堆栈*/
char str1[]="XYZAZYX"; /*回文字符序列1*/
char str2[]="XYZBZYX"; /*回文字符序列2*/
char q1,s1,q2,s2;
int i;
InitQueue(&LQueue1); /*初始化链式循环队列1*/
InitQueue(&LQueue2); /*初始化链式循环队列2*/
InitStack(&LStack1); /*初始化链式堆栈1*/
InitStack(&LStack2); /*初始化链式堆栈2*/
for(i=0;i<strlen(str1);i++)
{
EnterQueue(&LQueue1,str1[i]); /*依次把字符序列1入队*/
EnterQueue(&LQueue2,str2[i]); /*依次把字符序列2入队*/
PushStack(LStack1,str1[i]); /*依次把字符序列1进栈*/
PushStack(LStack2,str2[i]); /*依次把字符序列2进栈*/
}
printf("字符序列1:\n");
printf("出队序列 出栈序列\n");
while(!StackEmpty(LStack1)) /*判断堆栈1是否为空*/
{
DeleteQueue(&LQueue1,&q1); /*字符序列依次出队,并把出队元素赋值给q*/
PopStack(LStack1,&s1); /*字符序列出栈,并把出栈元素赋值给s*/
printf("%5c",q1); /*输出字符序列1*/
printf("%10c\n",s1);
if(q1!=s1) /*判断字符序列1是否是回文*/
{
printf("字符序列1不是回文!");
return;
}
}
printf("字符序列1是回文!\n");
printf("字符序列2:\n");
printf("出队序列 出栈序列\n");
while(!StackEmpty(LStack2)) /*判断堆栈2是否为空*/
{
DeleteQueue(&LQueue2,&q2); /*字符序列依次出队,并把出队元素赋值给q*/
PopStack(LStack2,&s2); /*字符序列出栈,并把出栈元素赋值给s*/
printf("%5c",q2); /*输出字符序列2*/
printf("%10c\n",s2);
if(q2!=s2) /*判断字符序列2是否是回文*/
{
printf("字符序列2不是回文!\n");
return;
}
}
printf("字符序列2是回文!\n");
system("pause");
}
作业4 6-1 二叉树创建及遍历 (40 分)
实现二叉树创建及遍历算法。
函数接口定义:
void CreateBiTree(BiTree &T);//根据输入的字符串,创建二叉树。
void PreOrder(BiTree T);//先序遍历二叉树
void InOrder(BiTree T);//中序遍历二叉树
void PostOrder(BiTree T);//后序遍历二叉树
void LevelOrder(BiTree T);//层次遍历二叉树
其中 T
表示二叉树类型。
裁判测试程序样例:
#include<iostream>
using namespace std;
typedef struct BiNode{
char data;
struct BiNode *lchild,*rchild;
}BiTNode,*BiTree;
void CreateBiTree(BiTree &T);//根据输入的字符串,创建二叉树。
void PreOrder(BiTree T);//先序遍历二叉树
void InOrder(BiTree T);//中序遍历二叉树
void PostOrder(BiTree T);//后序遍历二叉树
void LevelOrder(BiTree T);//层次遍历二叉树
int main(){
BiTree T;
CreateBiTree(T);
cout<<"PreOrder:";
PreOrder(T);
cout<<endl<<"InOrder:";
InOrder(T);
cout<<endl<<"PostOrder:";
PostOrder(T);
cout<<endl<<"LevelOrder:";
LevelOrder(T);
return 0;
}
/* 请在这里填写答案 */
输入样例:
AB#C##D#EF###
输出样例:
输出拓扑序列。
PreOrder:ABCDEF
InOrder:BCADFE
PostOrder:CBFEDA
LevelOrder:ABDCEF
void CreateBiTree(BiTree &T){//根据输入的字符串,创建二叉树。
char n;
n = getchar();
if(n == '#')
T = NULL;
else
{
T = (BiTree)malloc(sizeof(struct BiNode));
T->data = n;
CreateBiTree(T -> lchild);
CreateBiTree(T -> rchild);
}
}
void PreOrder(BiTree T){
if(T){
cout<<T->data;
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
void InOrder(BiTree T){
if(T){
InOrder(T->lchild);
cout<<T->data;
InOrder(T->rchild);
}
}
void PostOrder(BiTree T){
if(T){
PostOrder(T->lchild);
PostOrder(T->rchild);
cout<<T->data;
}
}
void LevelOrder(BiTree T){
BiTree q[1000];
int front=0,rear =0;
if(T)
{
q[rear++]=T;
while(front!=rear)
{
BiTree now=q[front++];
printf("%c",now->data);
if(now->lchild) q[rear++]=now->lchild;
if(now->rchild) q[rear++]=now->rchild;
}
}
}
int GetHeight( BiTree BT ){//求深度
if(BT==NULL)
return 0;
int leftDepth = GetHeight(BT->lchild);
int rightDepth = GetHeight(BT->rchild);
if(leftDepth > rightDepth)
return leftDepth+1;
else
return rightDepth+1;
}
void PreorderPrintLeaves( BiTree BT ){
if(BT){
if(BT->lchild==NULL&&BT->rchild==NULL)
cout <<BT->data;
else{
PreorderPrintLeaves(BT->lchild);
PreorderPrintLeaves(BT->rchild);
}
}
}
int Leaves(BiTree BT){//统计叶子结点
int i = 0;
if (BT == NULL)
return 0;
else
if (BT->lchild == NULL && BT->rchild == NULL)
return 1;
else {
return Leaves(BT->lchild)+Leaves(BT->rchild);
}
}
int compareTree(BiTree T1,BiTree T2){
bool T1isNULL=(T1==NULL);
bool T2isNULL=(T2==NULL);
if(T1isNULL!=T2isNULL)
return 1;
if(T1isNULL==T2isNULL)
return 0;//两个都是空
if(T1->data!=T2->data)
return 1;
else
return (compareTree(T1->lchild,T2->lchild)&compareTree(T1->rchild,T2-rchild))||(compareTree(T1->rchild,T2->lchild)&compareTree(T1->lchild,T2-rchild));
}
void ChangeLR(BiTree &T){
BiTree temp;
if(T->lchild==NULL&&T->rchild==NULL)
return;
else{
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
}
ChangeLR(T->lchild);
ChangeLR(T->rchild);
}
作业5 heffman树
void Select(HuffmanTree HT, int len, int& s1, int& s2) {
int x1 = 0, x2 = 0;
int min1 = 1000, min2 = 1000;
for (int i = 1; i <= len; i++) {
if (HT[i].parent == 0 && HT[i].weight < min1) {
min2 = min1;
x2 = x1;
min1 = HT[i].weight;
x1 = i;
}
else if(HT[i].parent == 0 && HT[i].weight < min2){
min2 = HT[i].weight;
x2 = i;
}
}
s1 = x1;
s2 = x2;
}
void CreatHuffmanTree(HuffmanTree& HT, int n) {
int m;
int s1, s2;
if (n <= 1)return;
m = 2 * n - 1;
HT = new HTNode[m + 1];//0号单元未用,HT[m]表示根结点
for (int i = 1; i <= m; ++i)
{
HT[i].lchild = 0; HT[i].rchild = 0; HT[i].parent = 0;
}
for (int i = 1; i <= n; ++i) {
cin >> HT[i].ch;
cin >> HT[i].weight;
}
for (int i = n + 1; i <= m; ++i) //构造 Huffman树
{
Select(HT, i - 1, s1, s2);
//在HT[k](1≤k≤i-1)中选择两个其双亲域为0,
// 且权值最小的结点,
// 并返回它们在HT中的序号s1和s2
HT[s1].parent = i; HT[s2].parent = i;
//表示从F中删除s1,s2
HT[i].lchild = s1; HT[i].rchild = s2;
//s1,s2分别作为i的左右孩子
HT[i].weight = HT[s1].weight + HT[s2].weight;
//i 的权值为左右孩子权值之和
}
}
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode& HC, int n) {
HC = new char* [n + 1]; //分配n个字符编码的头指针矢量
char* cd = new char[n]; //分配临时存放编码的动态数组空间
cd[n - 1] = '\0'; //编码结束符
for (int i = 1; i <= n; ++i) { //逐个字符求赫夫曼编码
int start = n - 1;
int c = i;
int f = HT[i].parent;
while (f != 0) { //从叶子结点开始向上回溯,直到根结点
--start; //回溯一次start向前指一个位置
if (HT[f].lchild == c) cd[start] = '0'; //结点c是f的左孩子,则生成代码0
else cd[start] = '1'; //结点c是f的右孩子,则生成代码1
c = f; f = HT[f].parent; //继续向上回溯
} //求出第i个字符的编码
HC[i] = new char[n - start]; // 为第i 个字符编码分配空间
strcpy(HC[i], &cd[start]); //将求得的编码从临时空间cd复制到HC的当前行中
}
delete cd; //释放临时空间
} // CreatHuffanCode
作业6:图
邻接矩阵深度优先遍历
void DFS( MGraph Graph, Vertex V, void (*Visit)(Vertex) ){
Visited[V]=true;
Visit(V);
for(int i=0;i<Graph->Nv;i++){
if(Graph->G[V][i]==1&&!Visited[i])
DFS(Graph,i,Visit);
}
}
邻接表广度优先遍历
void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ){
int p[1001];
Visit(S);
int cnt=0,x=0;
Visited[S]=true;
p[cnt++]=S;
while(x!=cnt){
PtrToAdjVNode t=Graph->G[p[x++]].FirstEdge;
while(t){
int tn=t->AdjV;
if(!Visited[tn]){
p[cnt++]=tn;
Visit(tn);
Visited[tn]=true;
}
t=t->Next;
}
}
}
最小生成树 普利姆
void Prim( AMGraph G, char v )
{
int distance[G.vexnum];
int parent[G.vexnum];
//记录v的下标
int index=0;
int i,min=MaxInt,imin,count=0;
// 1.初始化这棵树,即以v为起始点,同时初始化数组distance[]
// 注:distance数组表示该树的任意一点到该点的最小距离
//寻找v的下标
for (i = 0; i < G.vexnum; i++)
if (G.vexs[i]==v)
{
index=i;
}
for (i = 0; i < G.vexnum; i++)
{
if (i==index)
{
distance[i]=0;
parent[i]=index;
}else
{
distance[i]=G.arcs[index][i];
parent[i]=index;
}
}
while (1)
{
if (count==G.vexnum-1)
{
break;
}
// 2.从小树现有的结点出发,寻找边权值最小的点:
for ( i = 0; i < G.vexnum; i++){
if (min>distance[i]&&distance[i]!=0)
{
//记录最小值及其下标
min=distance[i];
imin=i;
}
}
//更新已到达过得节点数
count++;
// 3.找到后输出该边
if (count<G.vexnum-1)
{
printf("%c->%c\n",G.vexs[parent[imin]],G.vexs[imin]);
}else
{
printf("%c->%c",G.vexs[parent[imin]],G.vexs[imin]);
}
//初始化min以便下次寻找
min=MaxInt;
// 4.将该点的distance数组中的值赋值为0,标记已经遍历过
distance[imin]=0;
// 5.循环遍历结点,更新distance[]数组
for ( i = 0; i < G.vexnum; i++){
if (distance[i]!=0&&G.arcs[i][imin]<MaxInt)
{
if (distance[i]>G.arcs[i][imin])
{
distance[i]=G.arcs[i][imin];
parent[i]=imin;
}
}
}
}
}
迪杰斯特拉算法
void ShortestPath_DIJ(AMGraph G, int v0){
int v=0,min;
for(int u=0;u<G.vexnum;u++){
S[u]=false; D[u]=G.arcs[v0][u];
if(D[u]<MaxInt)
Path[u]=v0;
else
Path[u]=-1;
}
D[v0]=0;S[v0]=true;
for(int u=0;u<G.vexnum-1;u++){
min=MaxInt;
for(int w=0;w<G.vexnum;w++)
if(S[w]==false&&D[w]<min)
{ v=w;
min=D[w];
}
S[v]=true;
for(int w=0;w<G.vexnum;w++)
if(!S[w])
if(G.arcs[v][w]<MaxInt&&D[v]+G.arcs[v][w]<D[w]){
D[w]=D[v]+G.arcs[v][w];
Path[w]=v;
}
}
}
作业7:查找
- 二分查找法(折半查找)
本题要求实现二分查找算法。
函数接口定义:
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。
Position BinarySearch( List L, ElementType X ){
int min,mid,max;
min=1;max=L->Last;
while(min<=max){
mid=(min+max)/2;
if(L->Data[mid]==X)
return mid;
else if(XData[mid])
max=mid-1;
else
min=mid+1;
}
return 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;
}
/* 你的代码将被嵌在这里 */
Position BinarySearch( List L, ElementType X ){
int min,mid,max;
min=1;max=L->Last;
while(min<=max){
mid=(min+max)/2;
if(L->Data[mid]==X)
return mid;
else if(X<L->Data[mid])
max=mid-1;
else
min=mid+1;
}
return NotFound;
}
- 线性检测法
试实现线性探测法的查找函数。
函数接口定义:
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;
}
/* 你的代码将被嵌在这里 */
Position Find( HashTable H, ElementType Key ){
int num,newpos;
num=newpos=Hash(Key,H->TableSize);
int i=0;
while(H->Cells[newpos].Data!=Key&&H->Cells[newpos].Info!=Empty){
i++;
if(i>H->TableSize) return ERROR;
else
newpos=(num+i)%H->TableSize;
}
return newpos;
}
- 二叉排序树查找操作
本题要求实现二叉排序树的查找操作。
函数接口定义:
BSTree SearchBST(BSTree T,ElemType e);
其中BSTree结构定义如下:
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct BSTNode
{
ElemType data;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
BSTree CreateBST();/* 二叉排序树创建,由裁判实现,细节不表 */
BSTree SearchBST(BSTree T,ElemType e);
void Inorder(BSTree T);/* 中序遍历,由裁判实现,细节不表 */
int main()
{
BSTree T,result;
ElemType n,e;
T = CreateBST();
printf("Inorder:"); Inorder(T); printf("\n");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&e);
result = SearchBST(T,e);
if(result) printf("%d is found\n",result->data);
else printf("%d is not found\n",e);
}
return 0;
}
/* 你的代码将被嵌在这里 */
BSTree SearchBST(BSTree T,ElemType e){
if(!T||T->data==e)
return T;
else if(e<T->data)
return SearchBST(T->lchild,e);
else
return SearchBST(T->rchild,e);
}
- 二叉排序树操作集
本题要求实现给定二叉搜索树的5种常用操作。
函数接口定义:
BinTree Insert( BinTree BST, ElementType X );
BinTree Delete( BinTree BST, ElementType X );
Position Find( BinTree BST, ElementType X );
Position FindMin( BinTree BST );
Position FindMax( BinTree BST );
其中BinTree结构定义如下:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
函数Insert将X插入二叉搜索树BST并返回结果树的根结点指针;
函数Delete将X从二叉搜索树BST中删除,并返回结果树的根结点指针;如果X不在树中,则打印一行Not Found并返回原树的根结点指针;
函数Find在二叉搜索树BST中找到X,返回该结点的指针;如果找不到则返回空指针;
函数FindMin返回二叉搜索树BST中最小元结点的指针;
函数FindMax返回二叉搜索树BST中最大元结点的指针。
二叉排序树
BinTree Delete( BinTree BST, ElementType X ){
if(BST == NULL){ printf("Not Found\n"); return BST;}
else if(BST->Data == X){
if(BST->Left != NULL && BST->Right != NULL){
BinTree p = FindMax(BST->Left);
//while(p->Right) p = p->Right;
p->Right = BST->Right;
p = BST->Left;
free(BST);
return p;
}
else if(BST->Left != NULL && BST->Right == NULL){
BinTree p = BST->Left;
free(BST);
return p;
}
else if(BST->Right != NULL && BST->Left == NULL){
BinTree p = BST->Right;
free(BST);
return p;
}
else if((BST->Left == NULL) && (BST->Right == NULL)){
BinTree p = BST;
free(p);
return NULL;
}
}
else if(X < BST->Data) {
BST->Left = Delete(BST->Left, X);
return BST;
}
else if(X > BST->Data){ BST->Right = Delete(BST->Right, X); return BST;}
}
BinTree Delete(BinTree BST, ElementType X) {
Position Tmp;
if (!BST) {
printf("Not Found\n");
return BST;
}
else {
if (X < BST->Data)
BST->Left = Delete(BST->Left, X);
else if (X > BST->Data)
BST->Right = Delete(BST->Right, X);
else {
if (BST->Left && BST->Right) {
Tmp = FindMin(BST->Right);
// Tmp=BST->Right;
// while(Tmp->Left)
// Tmp=Tmp->Left;
BST->Data = Tmp->Data;
BST->Right = Delete(BST->Right, BST->Data);
}
else {
Tmp = BST;
if (!BST->Left)
BST = BST->Right;
else
BST = BST->Left;
free(Tmp);
}
}
}
return BST;
}
BinTree Insert( BinTree BST, ElementType X ) {
if(BST == NULL){
BST = (BinTree)malloc(sizeof(Position));
BST->Data = X;
BST->Left = NULL;
BST->Right = NULL;
}
else if(X > BST->Data) BST->Right =Insert(BST->Right, X);
else if(X < BST->Data) BST->Left = Insert(BST->Left, X);
return BST;
}//diyidabug
Position Find( BinTree BST, ElementType X ){
if(BST == NULL) return 0;
else if(BST->Data == X) return BST;
else if(X < BST->Data) Find(BST->Left, X);
else Find(BST->Right, X);
}
Position FindMin( BinTree BST ){
if(!BST) return BST;
if(BST->Left == NULL) return BST;
else FindMin(BST->Left);
}
Position FindMax( BinTree BST ){
if(!BST) return BST;
if(BST->Right == NULL) return BST;
else FindMax(BST->Right);
}
//
BinTree Insert( BinTree BST, ElementType X ){
if(BST==NULL){
BST=(BinTree)malloc(sizeof(struct TNode));
BST->Data=X;
BST->Left=NULL;
BST->Right=NULL;
}
else
if(X<BST->Data)
BST->Left=Insert(BST->Left,X);
else if(X>BST ->Data)
BST->Right=Insert(BST->Right,X);
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X ){
BinTree Tmp;
if(BST==NULL){
printf("Not Found\n");
}
else if(X<BST->Data)
return Delete(BST->Left,X);
else if(X>BST->Data)
return Delete(BST->Right,X);
else{
if(BST->Left && BST->Right) {
Tmp=FindMin(BST->Right); /* 在右子树中找到最小结点填充删除结点 */
BST->Data = Tmp ->Data;
BST->Right=Delete(BST->Right,BST->Data);/* 递归删除要删除结点的右子树中最小元素 */
}
else
{ /* 被删除结点有一个或没有子结点*/
Tmp = BST;
if(!BST->Left) BST = BST->Right; /*有右孩子或者没孩子*/
else if(!BST->Right) BST = BST->Left;/*有左孩子,一定要加else,不然BST可能是NULL,会段错误*/
free(Tmp); /*如无左右孩子直接删除*/
}
}
return BST;
}
Position Find( BinTree BST, ElementType X ){
if(BST==NULL)
return BST;
if(!BST||BST->Data==X)
return BST;
else if(X<BST->Data)
return Find(BST->Left,X);
else
return Find(BST->Right,X);
return BST;
}
Position FindMin( BinTree BST ){
if(BST==NULL)
return BST;
else
if(BST->Left!=NULL)
FindMin(BST->Left);
else
return BST;
}
Position FindMax( BinTree BST ){
if(BST==NULL)
return BST;
else
if(BST->Right!=NULL)
FindMin(BST->Right);
else
return BST;
}
x(BST->Right);
}
//
BinTree Insert( BinTree BST, ElementType X ){
if(BST==NULL){
BST=(BinTree)malloc(sizeof(struct TNode));
BST->Data=X;
BST->Left=NULL;
BST->Right=NULL;
}
else
if(X<BST->Data)
BST->Left=Insert(BST->Left,X);
else if(X>BST ->Data)
BST->Right=Insert(BST->Right,X);
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X ){
BinTree Tmp;
if(BST==NULL){
printf("Not Found\n");
}
else if(X<BST->Data)
return Delete(BST->Left,X);
else if(X>BST->Data)
return Delete(BST->Right,X);
else{
if(BST->Left && BST->Right) {
Tmp=FindMin(BST->Right); /* 在右子树中找到最小结点填充删除结点 */
BST->Data = Tmp ->Data;
BST->Right=Delete(BST->Right,BST->Data);/* 递归删除要删除结点的右子树中最小元素 */
}
else
{ /* 被删除结点有一个或没有子结点*/
Tmp = BST;
if(!BST->Left) BST = BST->Right; /*有右孩子或者没孩子*/
else if(!BST->Right) BST = BST->Left;/*有左孩子,一定要加else,不然BST可能是NULL,会段错误*/
free(Tmp); /*如无左右孩子直接删除*/
}
}
return BST;
}
Position Find( BinTree BST, ElementType X ){
if(BST==NULL)
return BST;
if(!BST||BST->Data==X)
return BST;
else if(X<BST->Data)
return Find(BST->Left,X);
else
return Find(BST->Right,X);
return BST;
}
Position FindMin( BinTree BST ){
if(BST==NULL)
return BST;
else
if(BST->Left!=NULL)
FindMin(BST->Left);
else
return BST;
}
Position FindMax( BinTree BST ){
if(BST==NULL)
return BST;
else
if(BST->Right!=NULL)
FindMin(BST->Right);
else
return BST;
}