17级寒假任务
第一章
1.用自己对数据结构的认识描述下列问题:
- 何为基本型数据类型
- 何为结构型数据类型
- 请用任c语言为例,说明他所提供的数据类型,那两种为基本型?哪一种为结构型。
- 答:基本型数据类型是指程序语言已经定义的数据类型。
- 答:结构型数据类型是指在基本型数据类型的基础上用户自定义的数据类型。
- 答:C语言中包括的数据类型有基本类型、空类型、枚举类型和派生类型,基本类型和枚举类型为基本型,派生类型为结构型。
2.把下面程序流程用代码表示出来,并且求下列算法中x←x+1的执行次数和时间复杂度。
for i←1 to n to
j←1
for k←j+1 to n do
x←x+1
end
end
解:代码如下:
for(i=1;i<n;i++)
j=1; /*基本语句*/
for(k=j+1;k<n;k++)
x=x+1; /*基本语句*/
执行次数:i=1时k由2到n,(n-1)次,i=2时k=2到n,(n-1)次,依次类推可知执行次数为
n*(n-1)
时间复杂性:T(n)=O(n2)
第二章
1、有两个带头结点单链表(有序),将两个单链表和成一个单链表使得仍然有序
例如:单链表X:1,3,5,7
单链表Y:2,4,6,8
合成的单链表Z:1,2,3,4,5,6,7,8
编写程序:
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
}SLNode;
void sort(SLNode *l1,SLNode *l2); //两个链表融合,插入排序函数
void output(SLNode *head); //输出链表
void input(SLNode *head,int num); //输入链表
void input(SLNode *head,int num)
{
SLNode *tmp;
SLNode *end;
end=head;
printf("请输入链表节点:\n");
for(int i=0;i!=num;i++)
{
tmp=(SLNode *)malloc(sizeof(SLNode));
scanf("%d",&tmp->data);
end->next=tmp;
tmp->next=NULL;
end=tmp;
}
}
void sort(SLNode *l1,SLNode *l2)
{
SLNode *p1,*p2,*temp;
p1=l1;
p2=l2->next;
while(p1->next&&p2)
{
if(p1->next->data>p2->data)
{
temp=p2->next;
p2->next=p1->next;
p1->next=p2;
p2=temp;
}
else
p1=p1->next;
}
if(p2)
p1->next=p2;
}
void output(SLNode *head)
{
printf("合并后的链表为:\n");
while(head->next)
{
printf("%d ",head->next->data);
head=head->next;
}
printf("\n");
}
int main()
{
int n;
SLNode *X,*Y; //两个链表的头,下面四行初始化链表
X=(SLNode*)malloc(sizeof(SLNode));
Y=(SLNode*)malloc(sizeof(SLNode));
X->next=NULL;
Y->next=NULL;
//两个链表输入
printf("请输入第一个链表节点数:\n");
scanf("%d",&n);
input(X,n);
printf("请输入第二个链表节点数:\n");
scanf("%d",&n);
input(Y,n);
//合并链表并排序
sort(X,Y);
//输出合并后的链表
output(X);
}
2、利用链式表实现对student存储
typedef struct
{
int num;
int score;
char name[20];
}student;
要求可以随意输入多个学生信息,然后存储到链表中,任何可以对学生进行删除、增加(增加可以增加多个增加到相应的位置)、可以对学生进行name的查询,判断是否存在。修改链式表存在的学生(提示:只考虑存在不考虑不存在的情况,修改是修改第几个的学生信息,包括num,score,name信息);然后将最后的学生进行逆置输出
例如:
提示:输入学生信息的1代表num,2代表score,3代表name
提示3个节点表示存在3个学生,表示链表存储学生的个数
提示:这里第一个学生插入的位置是0,第二个是一
|
编写程序:
/*1.输入多个学生信息,然后存储到链表中;
2.可以对学生进行删除、增加(增加可以增加多个增加到相应的位置);
3.可以对学生进行name的查询,判断是否存在;
4.修改链式表存在的学生(提示:只考虑存在不考虑不存在的情况,修改是修改第几个的学生信息,包括num,score,name信息);
5.然后将最后的学生进行逆置输出*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
typedef struct student
{
int num;
int score;
char name[20];
struct student *next;
}stu;
int n;
void print(stu * head);
/*输入一个新的链表*/
stu * creat()
{
stu *p1,*p2,*head;
int i,t,k=1;
printf("输入学生信息的个数: ");
scanf("%d",&t);
head=NULL;
printf("输入%d个学生的信息(姓名-学号-成绩)\n",t);
for(i=0;i<t;i++)
{
p1=(stu *)malloc(sizeof(stu));
scanf("%s%ld%d",&p1->name,&p1->num,&p1->score);
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
}
p2->next=NULL;
return head;
}
/*删除一个新的纪录*/
stu * del(stu * head,long num)
{
stu *p1,*p2;
if(head==NULL)
printf("表内没有学生信息!\n");
else
{
p1=head;
while(p1->num!=num && p1->next!=0)
{
p2=p1;
p1=p1->next;
}
if(p1->num==num)
{
if(p1==head)
{
head=p1->next;
}
else
{
p2->next=p1->next;
}
printf("删除学号:%ld成功\n",num);
n=n-1;
}
else
printf("没有%ld这个学号!\n",num);
}
return head;
}
/*插入一个新的记录*/
stu *insert(stu * head, stu * stud)
{
stu *p1,*p2,*p0;
p0=stud;p1=head;
if(head==0)
{
head=p0;stud->next=0;
}
else
{
while(p1->num<p0->num && p1->next!=0)
{
p2=p1;p1=p1->next;
}
if(p1->num>=p0->num)
{
if(p1==head)
{
head=p0;
p0->next=p1;
}
else
{
p2->next=p0;
p0->next=p1;
}
}
else
{
p1->next=p0;
p0->next=NULL;
}
}
n=n+1;
return head;
}
/*查找学生信息*/
void search(stu *head)
{
char name[10];
stu *p;
printf("请输入要查找的姓名: ");
scanf("%s",&name);
p=head;
while(p)
{
if(strcmp(p->name,name)==0)
{
printf("%s的信息为:\n",p->name);
printf("%-10s %ld %d\n",p->name,p->num,p->score);
break;
}
p=p->next;
}
}
/*修改信息*/
void change(stu *head)
{
char name[10];
stu *p=NULL;
printf("请输入要修改的学生姓名: ");
scanf("%s",&name);
p=head;
while(p)
{
if(strcmp(p->name,name)==0)
{
printf("%s的信息为:\n",p->name);
printf("%-10s %ld %d\n",p->name,p->num,p->score);
printf("请输入修改信息(姓名-学号-成绩)\n");
scanf("%s%ld%d",&p->name,&p->num,&p->score);
break;
}
p=p->next;
}
}
/* 逆序输出*/
void R_print(stu *p)
{
if(p->next)
R_print(p->next);
printf("%-10s %ld %d\n",p->name,p->num,p->score);
}
/*显示全部学生成绩*/
void print(stu * head)
{
stu * p;
printf("此时的%d个学生信息是:\n",n);
p=head;
if(head!=0)
{
while(p!=0)
{
printf("%-10s %ld %d\n",p->name,p->num,p->score);
p=p->next;
}
}
}
void main()
{
stu * head=NULL,*stud;
long del_num;
int i=1,m;
printf("—————链表实现对学生信息管理—————\n\n");
printf("\n————————输入——————————\n");
head=creat();
print(head);
printf("\n————————删除——————————\n");
printf("输入要删除的学号:");
scanf("%ld",&del_num);
head=del(head,del_num);
print(head);
printf("\n————————插入——————————\n");
printf("请输入插入的个数: ");
scanf("%d",&m);
printf("输入%d个学生的信息(姓名-学号-成绩)\n",m);
for(i=0;i<m;i++)
{
stud=(stu *)malloc(sizeof(stu));
scanf("%s%ld%d",&stud->name,&stud->num,&stud->score);
}
stud->next=NULL;
head=insert(head,stud);
print(head);
printf("\n————————查找——————————\n");
search(head);
printf("\n————————修改——————————\n");
change(head);
printf("\n————————逆序——————————\n");
printf("逆序输出学生信息\n");
R_print(head);
system("pause");
}
第三章
1. 利用一个堆栈,如果输出序列由A、B、C组成,试给出全部可能得序列和不可能的输出序列。
ABC:A进A出 B进B出 C进C出
CBA:AB进 C进 C出 BA出
ACB:a进a出 bc进cb出
BAC:ab进ba出 c进c出
bca:a进 b进 b出 c进c出 a出
不可能的输出序列:CAB
2. 使用数据结构实现判断一个等式中的左右括号是否一致,例如输入 ((a+b)* (c-d) )
/*算法思路: 算术表达式中右括号和左括号匹配的次序正好符合后到的括号要最先被匹配的“后进先出”堆栈的特点*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MaxStackSize 100
typedef char DataType;
#include"SeqStack.h"
void ExpIsCorrect(char exp[],int n)
{
SeqStack myStack;
int i;
char c;
StackInitiate(&myStack);
for(i=0;i<n;i++)
{
if((exp[i]=='(')||(exp[i]=='[')||(exp[i]=='{'))
StackPush(&myStack,exp[i]); //入栈
else if( exp[i]==')' && StackNotEmpty(myStack) && StackTop(myStack,&c) && c=='(')
StackTop(myStack,&c); //出栈
else if( exp[i]==')' && StackNotEmpty(myStack) && StackTop(myStack,&c) && c!='(')
{
printf("左右括号配对次序不正确!\n");
return;
; }
else if(exp[i]==']' && StackNotEmpty(myStack) && StackTop(myStack,&c) && c=='[')
StackPop(&myStack,&c); //出栈
else if(exp[i]==']' && StackNotEmpty(myStack) && StackTop(myStack,&c) && c!='[')
{
printf("左右括号配对次序不正确!\n");
return;
}
else if(exp[i]=='}' && StackNotEmpty(myStack) && StackTop(myStack,&c) && c=='{')
StackPop(&myStack,&c); //出栈
else if(exp[i]=='}' && StackNotEmpty(myStack) && StackTop(myStack,&c) && c!='{')
{
printf("左右括号配对次序不正确!\n");
return;
}
else if(((exp[i]==')')||(exp[i]==']')||(exp[i]=='}'))&&!StackNotEmpty(myStack))
{
printf("右括号多于左括号!\n");
return;
}
}
if(StackNotEmpty(myStack))
printf("左括号多于右括号!\n");
else
printf("左右括号匹配正确!\n");
}
void main(void)
{
char a[]="((a+b)*(c-d))"; //测试1,左右括号匹配次序不正确
int n1=strlen(a);
ExpIsCorrect(a,n1);
printf("\n");
system("pause");
}
第四章
1,(基础题)实现静态数组下串的插入,删除,取子串操作。
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
#include"SString.h"
void main(void)
{
String myString1={"Data ",5},myString2={"Structure",9},myString3;
Initiate(&myString3);
int i;
printf("---------插入---------\n");
Insert(&myString2,0,myString1);
for(i=0;i<myString2.length;i++)
printf("%c",myString2.str[i]);
printf("\n---------删除---------\n");
Delete(&myString2,10,3);
for(i=0;i<myString2.length;i++)
printf("%c",myString2.str[i]);
printf("\n---------取子串---------\n");
SubString(myString2,0,4,&myString3);
for(i=0;i<myString3.length;i++)
printf("%c",myString3.str[i]);
printf("\n");
system("pause");
}
SString.h
typedef struct
{
char str[MaxSize];
int length;
}String;
//初始化
void Initiate(String *S)
{
S->length=0;
}
//插入子串
int Insert(String *S,int pos,String T) //在串S的pos位置插入子串T
{
int i;
if(pos<0||pos>S->length)
{
printf("pos参数错误!\n");
return 0;
}
else if(S->length+T.length>MaxSize)
{
printf("数组空间不足无法插入!\n");
return 0;
}
else
{
for(i=S->length-1;i>=pos;i--)
S->str[i+T.length]=S->str[i]; //依次后移数据元素
for(i=0;i<T.length;i++)
S->str[pos+i]=T.str[i]; //插入
S->length =S->length+T.length; //产生新的串长度
return 1;
}
}
//删除子串
int Delete(String *S,int pos,int len)
{
int i;
if(S->length<=0)
{
printf("数组中无数据元素可删!\n");
return 0;
}
else if(pos<0||len<0||pos+len>S->length)
{
printf("参数pos和len不合法!\n");
return 0;
}
else
{
for(i=pos+len;i<=S->length;i++)
{
S->str[i-len]=S->str[i]; //依次前移数据元素
S->length =S->length-len; //产生新的串长度值
}
}
}
//取子串
int SubString(String S,int pos,int len,String *T) //取串S中从pos位置开始长度为len的子串赋值给串T
{
int i;
if(pos<0||len<0||pos+len>S.length)
{
printf("参数pos和len不合法!\n");
return 0;
}
else
{
for(i=0;i<len;i++)
T->str[i]=S.str[pos+i]; //给子串T赋值
T->length=len;
return 1; //给子串的长度赋值
}
}
第五章
1,(基础题)设计算法实现两个矩阵的加法和乘法。
#include<stdio.h>
#include<stdlib.h>
void Add(int a[],int b[],int c[],int n)
{
int i;
for(i=0;i<=n*(n+1)/2-1;i++)
c[i]=a[i]+b[i];
}
void Multiply(int a[],int b[],int c[],int n)
{
int i;
for(i=0;i<=n*(n+1)/2-1;i++)
c[i]=a[i]*b[i];
}
void Print(int a[],int n)
{
int i,j,k;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i>=j)
k=i*(i-1)/2+j-1;
else
k=j*(j-1)/2+i-1;
printf("%-5d",a[k]);
}
printf("\n");
}
}
void main(void)
{
int a[]={1,2,3,4,5,6},b[]={10,20,30,40,50,60},c[6],d[6];
int n=3;
printf("---矩阵a ---\n");
Print(a,n);
printf("\n---矩阵b ---\n");
Print(b,n);
printf("\n---矩阵加法---\n");
Add(a,b,c,n);
Print(c,n);
printf("\n---矩阵乘法---\n");
Multiply(a,b,d,n);
Print(d,n);
system("pause");
}
第六章
1,输入某个字符串,用递归的方法实现该字符串的全排列。如:
#include<stdio.h>
#include<stdlib.h>
#define swap(a,b,t) ((t)=(a),(a)=(b),(b)=(t)) //宏定义,包含函数
int count=0;
int num=3; //定义了全局变量作用是需要给多少个元素进行排列
void permutation(char *ch, int min, int max,int n)
{
int i;
char temp;
if (n==0) //递归条件的改变
{
printf("%s\n",ch);
count++;
}
else
{
for (i=min;i<=max;i++)
{
swap(ch[i],ch[min],temp);
permutation(ch,min+1,max,n-1); //每次给n-1和上一个代码的不同点
swap(ch[i],ch[min],temp);
}
}
}
void main()
{
char p[] = {"abc"};
permutation(p, 0, sizeof(p)-1-1,num);
printf("count=%d\n", count);
system("pause");
}
第七章
A |
1,求二叉树的深度和所有节点数值域的值(自己创建一棵树)。
B |
C |
D |
E |
F |
G |
该二叉树的深度为:3
所有节点的数值域为: ?
2,查找二叉树中的某个数据元素。
BiTreeNode *Search(BiTreeNode *bt,DataType x)
{
BiTreeNode *p;
if(bt==NULL)
return NULL;
if(bt->data==x)
return bt;
if(bt->leftChild!=NULL)
{
p=Search(bt->leftChild,x);
if(p!=NULL)
return p;
}
if(bt->rightChild!=NULL)
{
p=Search(bt->rightChild,x);
if(p!=NULL)
return p;
}
return NULL;
}
第八章
1、分别利用深度和广度优先搜索序列算法对图进行排序:
如地址有A、B、C、D、E(有向连通图)
A到B 10,A到E 20,B到D 30,C到B 40,D到C 50
输出:
深度优先搜索序列:A B D C E
广度优先搜索序列:A B E D C
2、最短路径问题
如A B C D E F
{0,2,5} {0,3,30} {1,0,2} {1,4,8} {2,1,15} {2,5,7} {4,3,4} {5,3,10} {5,4,18}
如
请输入起点和终点:A C
输出:A到C的最短路径为A--->C 5
如
请输入起点和终点:A B
输出:A到B的最短路径为A--->C 5,C--->B 15
第九章
1.有一长度为10000的数组,数组中的每个元素的值等于其下标,现要求使用冒泡排序,将数组中的所有元素降序排序,并计算排序所需时间。
编写程序:
#include<stdio.h>
#include<stdlib.h>
typedef int DataType;
#define N 10000
void BubbleSort(DataType a[],int n);
void Print(DataType a[],int n);
/*冒泡排序排序算法*/
void BubbleSort(DataType a[],int n)
{
int i,j,flag=1;
DataType temp;
for(i=1;i<n&&flag==1;i++)
{
flag=0;
for(j=0;j<n-i;j++)
{
if(a[j]<a[j+1]) //降序排列
{
flag=1;
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
/*打印函数*/
void Print(DataType a[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
/*测试函数*/
void main(void)
{
int i,a[N];
for(i=0;i<N;i++)
{
a[i]=i;
}
BubbleSort(a,N);
Print(a,N);
system("pause");
}
时间复杂度:比较次数:n(n-1)/2 移动次数:n(n-1)/2
T(n)= n(n-1)/2+ n(n-1)/2
O(n)=n2
2.有一长度为10000的数组,数组中的每个元素的值等于其下标,现要求写一个使用快速排序的函数QuickSort(可参考数据结构教材书),调用该函数对数组中的所有元素进行降序排序,计算排序所需时间
/*快速排序排序算法*/
void QuickSort(DataType a[],int low,int high)
{
int i=low,j=high;
DataType temp=a[low];
while(i<j)
{
while(i<j&&temp<=a[j])
j--;
if(i<j)
{
a[i]=a[j];
i++;
}
while(i<j&&a[i]<temp)
i++;
if(i<j)
{
a[j]=a[i];
j--;
}
}
a[i]=temp;
if(low<i)
QuickSort(a,low,i-1); //对左端子集合进行递归
if(i<high)
QuickSort(a,j+1,high); //对右端子集合进行递归
}
时间复杂度:
第十章
1,(基础题)设计用二分法查找一组数据中的某个数据。
#include<stdio.h>
#include<stdlib.h>
int BSearch(int a[],int x,int low,int high)
{
int mid;
if(low>high) //查找不成功
return -1;
mid=(low+high)/2;
if(x==a[mid]) //查找成功
return mid;
else if(x<a[mid])
return BSearch(a,x,low,mid-1); //在下半区查找
else
return BSearch(a,x,mid+1,high); //在上半区查找
}
void main(void)
{
int a[]={1,3,4,5,17,18,31,33};
int x;
int bn;
printf("请输入需要查找的数: ");
scanf("%d",&x);
bn=BSearch(a,x,0,7);
if(bn==-1)
printf("x不在数组a中!");
else
printf("%d在数组a的下标%d中\n",x,bn);
system("pause");
}