【上机考试复习】数据结构头歌复习题(全部)
·
线性表
实现一个顺序存储的线性表
/*************************************************************
date: April 2017
copyright: Zhu En
DO NOT distribute this code without my permission.
**************************************************************/
// 顺序表操作实现文件
//////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include "Seqlist.h"
SeqList* SL_Create(int maxlen)
// 创建一个顺序表
// 与SqLst_Free()配对
{
SeqList* slist=(SeqList*)malloc(sizeof(SeqList));
slist->data = (T*)malloc(sizeof(T)*maxlen);
slist->max=maxlen;
slist->len=0;
return slist;
}
void SL_Free(SeqList* slist)
// 释放/删除 顺序表
// 与SqLst_Create()配对
{
free(slist->data);
free(slist);
}
void SL_MakeEmpty(SeqList* slist)
// 置为空表
{
slist->len=0;
}
int SL_Length(SeqList* slist)
// 获取长度
{
return slist->len;
}
bool SL_IsEmpty(SeqList* slist)
// 判断顺序表是否空
{
return 0==slist->len;
}
bool SL_IsFull(SeqList* slist)
// 判断顺序表是否满
{
return slist->len==slist->max;
}
T SL_GetAt(SeqList* slist, int i)
// 获取顺序表slist的第i号结点数据
// 返回第i号结点的值
{
if(i<0||i>=slist->len)
{
printf("SL_GetAt(): location error when reading elements of the slist!\n");
SL_Free(slist);
exit(0);
}
else
{
return slist->data[i];
}
}
void SL_SetAt(SeqList* slist, int i, T x)
// 设置第i号结点的值(对第i号结点的数据进行写)
{
if(i<0||i>=slist->len)
{
printf("SL_SetAt(): location error when setting elements of the slist!\n");
SL_Free(slist);
exit(0);
}
else
{
slist->data[i]=x;
}
}
bool SL_InsAt(SeqList* slist, int i, T x)
// 在顺序表的位置i插入结点x, 插入d[i]之前
// i的有效范围[0,plist->len]
{
if (i<0 || i>slist->len || slist->len==slist->max)
{
printf("SL_InsAt(): location error, or slist full.\n");
return false;
}
for (int j=slist->len; j>=i+1; j--)
{
slist->data[j]=slist->data[j-1];
}
slist->data[i]=x;
slist->len++;
return true;
}
T SL_DelAt(SeqList* slist, int i)
// 删除顺序表plist的第i号结点
// i的有效范围应在[0,plist->len)内,否则会产生异常或错误。
// 返回被删除的数据元素的值。
{
if (i<0 || i>=slist->len)
{
printf("SL_DelAt(): location error!\n");
SL_Free(slist);
exit(0);
}
T res=slist->data[i];
for (int j=i; j<slist->len-1; j++)
{
slist->data[j] = slist->data[j+1];
}
slist->len--;
return res;
}
int SL_FindValue(SeqList* slist, T x)
// 在顺序表表中查找第一个值为x的结点,返回结点的编号
// 返回值大于等于0时表示找到值为x的结点的编号,-1表示没有找到
{
int i=0;
while(i<slist->len && slist->data[i]!=x) i++;
if (i<slist->len) return i;
else return -1;
}
int SL_DelValue(SeqList* slist, T x)
// 删除第一个值为x的结点,
// 存在值为x的结点则返回结点编号, 未找到返回-1
{
int i=SL_FindValue(slist, x);
if (i>=0)
{
SL_DelAt(slist, i);
}
return i;
}
void SL_Print(SeqList* slist)
// 打印整个顺序表
{
if (slist->len==0)
{
printf("The slist is empty.\n");
return;
}
//printf("The slist contains: ");
for (int i=0; i<slist->len; i++)
{
printf("%d ", slist->data[i]);
}
printf("\n");
}
实现一个链接存储的线性表
/*************************************************************
date: April 2017
copyright: Zhu En
DO NOT distribute this code without my permission.
**************************************************************/
// 单链表实现文件
#include <stdio.h>
#include <stdlib.h>
#include "LinkList.h"
LinkList* LL_Create()
// 创建一个链接存储的线性表,初始为空表,返回llist指针。
{
LinkList* llist=(LinkList*)malloc(sizeof(LinkList));
llist->front=NULL;
llist->rear=NULL;
llist->pre=NULL;
llist->curr=NULL;
llist->position=0;
llist->len=0;
return llist;
}
void LL_Free(LinkList* llist)
// 释放链表的结点,然后释放llist所指向的结构。
{
LinkNode* node=llist->front;
LinkNode* nextnode;
while(node)
{
nextnode=node->next;
free(node);
node=nextnode;
}
free(llist);
}
void LL_MakeEmpty(LinkList* llist)
// 将当前线性表变为一个空表,因此需要释放所有结点。
{
LinkNode* node=llist->front;
LinkNode* nextnode;
while(node)
{
nextnode=node->next;
free(node);
node=nextnode;
}
llist->front=NULL;
llist->rear=NULL;
llist->pre=NULL;
llist->curr=NULL;
llist->position=0;
llist->len=0;
}
int LL_Length(LinkList* llist)
// 返回线性表的当前长度。
{
return llist->len;
}
bool LL_IsEmpty(LinkList* llist)
// 若当前线性表是空表,则返回true,否则返回TRUE。
{
return llist->len==0;
}
bool LL_SetPosition(LinkList* llist, int i)
// 设置线性表的当前位置为i号位置。
// 设置成功,则返回true,否则返回false(线性表为空,或i不在有效的返回)
// 假设线性表当前长度为len,那么i的有效范围为[0,len]
{
int k;
/* 若链表为空,则返回*/
if (llist->len==0) return false;
/*若位置越界*/
if( i < 0 || i > llist->len)
{ printf("LL_SetPosition(): position error");
return false;
}
/* 寻找对应结点*/
llist->curr = llist->front;
llist->pre = NULL;
llist->position = 0;
for ( k = 0; k < i; k++)
{
llist->position++;
llist->pre = llist->curr;
llist->curr = (llist->curr)->next;
}
/* 返回当前结点位置*/
return true;
}
int LL_GetPosition(LinkList* llist)
// 获取线性表的当前位置结点的编号
{
return llist->position;
}
bool LL_NextPosition(LinkList* llist)
// 设置线性表的当前位置的下一个位置为当前位置。
// 设置成功,则返回true,否则返回false(线性表为空,或当前位置为表尾)
{
if (llist->position >= 0 && llist->position < llist->len)
/* 若当前结点存在,则将其后继结点设置为当前结点*/
{
llist->position++;
llist->pre = llist->curr;
llist->curr = llist->curr->next;
return true;
}
else
{
return false;
}
}
T LL_GetAt(LinkList* llist)
// 返回线性表的当前位置的数据元素的值。
{
if(llist->curr==NULL)
{
printf("LL_GetAt(): Empty list, or End of the List.\n");
LL_Free(llist);
exit(1);
}
return llist->curr->data;
}
void LL_SetAt(LinkList* llist, T x)
// 将线性表的当前位置的数据元素的值修改为x。
{
if(llist->curr==NULL)
{
printf("LL_SetAt(): Empty list, or End of the List.\n");
LL_Free(llist);
exit(1);
}
llist->curr->data=x;
}
bool LL_InsAt(LinkList* llist, T x)
// 在线性表的当前位置之前插入数据元素x。当前位置指针指向新数据元素结点。
// 若插入失败,返回false,否则返回true。
{
LinkNode *newNode=(LinkNode*)malloc(sizeof(LinkNode));
if (newNode==NULL)
{
return false;
}
newNode->data=x;
if (llist->len==0)
{
/* 在空表中插入*/
newNode->next=NULL;
llist->front = llist->rear = newNode;
}
//当前位置为表头
else if (llist->pre==NULL)
{
/* 在表头结点处插入*/
newNode->next = llist->front;
llist->front = newNode;
}
else
{
/* 在链表的中间位置或表尾后的位置插入*/
newNode->next = llist->curr;
llist->pre->next=newNode;
}
//插入在表尾后
if (llist->pre==llist->rear)
llist->rear=newNode;
/* 增加链表的大小*/
llist->len++;
/* 新插入的结点为当前结点*/
llist->curr = newNode;
return true;
}
bool LL_InsAfter(LinkList* llist, T x)
// 在线性表的当前位置之后插入数据元素x。空表允许插入。当前位置指针将指向新结点。
// 若插入失败,返回false,否则返回true。
{
LinkNode *newNode=(LinkNode*)malloc(sizeof(LinkNode));
if (newNode==NULL) return false;
newNode->data=x;
if (llist->len==0)
{
/* 在空表中插入*/
newNode->next=NULL;
llist->front = llist->rear = newNode;
}
else if (llist->curr == llist->rear || llist->curr == NULL) {
/* 在尾结点后插入*/
newNode->next = NULL;
llist->rear->next=newNode;
llist->pre=llist->rear;
llist->rear=newNode;
llist->position=llist->len;
}
else
{
/* 在中间位置插入*/
newNode->next = llist->curr->next;
llist->curr->next=newNode;
llist->pre=llist->curr;
llist->position ++;
}
/* 增加链表的大小*/
llist->len ++;
/* 新插入的结点为当前结点*/
llist->curr = newNode;
return true;
}
bool LL_DelAt(LinkList* llist)
// 删除线性表的当前位置的数据元素结点。
// 若删除失败(为空表,或当前位置为尾结点之后),则返回false,否则返回true。
{
LinkNode *oldNode;
/* 若表为空或已到表尾之后,则给出错误提示并返回*/
if (llist->curr==NULL)
{
printf("LL_DelAt(): delete a node that does not exist.\n");
return false;
}
oldNode=llist->curr;
/* 删除的是表头结点*/
if (llist->pre==NULL)
{
llist->front = oldNode->next;
}
/* 删除的是表中或表尾结点*/
else if(llist->curr!=NULL)
{
llist->pre->next = oldNode->next;
}
if (oldNode == llist->rear)
{
/* 删除的是表尾结点,则修改表尾指针和当前结点位置值*/
llist->rear = llist->pre;
}
/* 后继结点作为新的当前结点*/
llist->curr = oldNode->next;
/* 释放原当前结点*/
free(oldNode);
/* 链表大小减*/
llist->len --;
return true;
}
bool LL_DelAfter(LinkList* llist)
// 删除线性表的当前位置的后面那个数据元素。
// 若删除失败(为空表,或当前位置时表尾),则返回false,否则返回true。
{
LinkNode *oldNode;
/* 若表为空或已到表尾,则给出错误提示并返回*/
if (llist->curr==NULL || llist->curr== llist->rear)
{
printf("LL_DelAfter(): delete a node that does not exist.\n");
return false;
}
/* 保存被删除结点的指针并从链表中删除该结点*/
oldNode = llist->curr->next;
llist->curr->next=oldNode->next;
if (oldNode == llist->rear)
{
/* 删除的是表尾结点*/
llist->rear = llist->curr;
}
/* 释放被删除结点*/
free(oldNode);
/* 链表大小减*/
llist->len --;
return true;
}
int LL_FindValue(LinkList* llist, T x)
// 找到线性表中第一个值为x的数据元素的编号。
// 返回值-1表示没有找到,返回值>=0表示编号。
{
LinkNode* p=llist->front;
int idx=0;
while(p!=NULL && p->data!=x)
{
idx++;
p = p->next;
}
if (idx>=llist->len)
{
return -1;
}
else
{
return idx;
}
}
int LL_DelValue(LinkList* llist, T x)
// 删除第一个值为x的数据元素,返回该数据元素的编号。如果不存在值为x的数据元素,则返回-1.
{
int idx=LL_FindValue(llist, x);
if (idx<0) return -1;
LL_SetPosition(llist, idx);
LL_DelAt(llist);
return idx;
}
void LL_Print(LinkList* llist)
// 打印整个线性表。
{
LinkNode* node=llist->front;
while (node)
{
printf("%d ", node->data);
node=node->next;
}
printf("\n");
}
函数
第1关 求和
#include<stdio.h>
//编写函数
/*********Begin*********/
int sum1(int n){
int sum = 0;
for(int i = 1; i <= n; i++){
sum += i;
}
return sum;
}
/*********End**********/
int main(void)
{
/*********Begin*********/
int n = 0;
scanf("%d", &n);
int sum = sum1(n);
printf("%d", sum);
/*********End**********/
return 0;
}
第2关 回文数计算
#include<stdio.h>
void solve(){
/*********Begin*********/
for(int i=200; i <= 999; i++){
int a = i/100; // 百位数字
int b = i%100%10; // 个位数字
if(a == b){
printf("%d\n",i);
}
}
for(int i=1000; i <= 3000; i++){
int a = i/1000; // 千位数字
int b = i/100%10; // 百位数字
int c = i/10%100%10; // 十位数字
int d = i%1000%100%10; // 个位数字
if(a == d && b == c){
printf("%d\n",i);
}
}
/*********End**********/
}
int main(void)
{
solve();
return 0;
}
第3关 编写函数求表达式的值
#include<stdio.h>
//编写题目要求的函数
/*********Begin*********/
double sum1(int n){
double sum = 1;
if(n==1)
return 1;
else {
for(int i = n+1; i >= 2; i--){ // 为啥是n+1呢??因为下面这个公式是用n推导的
sum = 1 + (double)(((i-1)*sum)/(2*i-1));
}
return sum;
}
}
/*********End**********/
int main(void)
{
/*********Begin*********/
// 1+1/3(1+2/5(1+......(1+(n-1)/(2n-1))))
int n=0;
double sum=0;
scanf("%d", &n);
sum = sum1(n);
printf("%.10lf", sum);
/*********End**********/
return 0;
}
第4关 阶乘数列
#include<stdio.h>
//编写函数
/*********Begin*********/
void sum1(int n){
long long int sum = 1;
if(n==1)
printf("1");
else {
for(int i = n; i >= 2; i--){
sum = 1 + i*sum;
}
printf("%lld",sum);
}
}
/*********End**********/
int main(void)
{
/*********Begin*********/
int n=0;
scanf("%d", &n);
sum1(n);
/*********End**********/
return 0;
}
第5关 亲密数
#include<stdio.h>
// 求因子的函数
int sum(int n){
int sum = 0;
for(int i = 1; i <= n/2; i++){
if(n%i == 0){
sum += i;
}
}
return sum;
}
void solve(){
/*********Begin*********/
for(int i = 1; i <= 3000; i++){ // i是第一个数字
int b = sum(i); // b是i的因子和
int c = sum(b); // c是b的因子和(c与i相同√)
// c==i:确定是亲密数
// b!=i且b<i:不会有6 6 这种出现同时输出结果不会是bi的反向输出
if(c == i && b != i && b < i){
printf("(%d,%d)", b,i);
}
}
/*********End**********/
}
int main(void)
{
solve();
return 0;
}
第6关 公约公倍数
#include<stdio.h>
//编写最大公约数GCD函数
/*********Begin*********/
long long int GCD(long long int a, long long int b){
long long int max = 1;
for(long long int i = 1; i <= a; i++){
if(a%i == 0 && b%i == 0){
max = i;
}
}
return max;
}
/*********End**********/
//编写最小公倍数LCM函数
/*********Begin*********/
int LCM(int a, int b){
}
/*********End**********/
int main(void)
{
long long int a,b;
/*********Begin*********/
scanf("%lld %lld",&a,&b);
if(a>b){
long long int temp = a;
a = b;
b = temp;
} // a一直小于b
if(a<0 || b <0){
printf("Input Error");
}else {
long long int max = GCD(a,b);
long long int min = a * b / max;
printf("%lld %lld",max,min);
}
/*********End**********/
return 0;
}
一维数组和二维数组
第1关 排序问题
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int a[10];
for(int i = 0; i < 10; i++){
scanf("%d", &a[i]);
}
for(int i = 0; i < 10; i++){
for(int j = i; j < 10; j++){
if(a[i] < a[j]){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
for(int i = 0; i < 10; i++){
printf("%d ", a[i]);
}
/*********End**********/
return 0;
}
第2关 查找整数
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int n = 0;
scanf("%d", &n);
int a[n];
for(int i = 0; i < n; i++){
scanf("%d", &a[i]);
}
int index = 0;
int temp = 0;
scanf("%d", &index);
for(int i = 0; i < n; i++){
if(a[i] == index){
printf("%d", i+1);
temp++;
break;
}
}
if(temp == 0){
printf("-1");
}
/*********End**********/
return 0;
}
第3关 计算数组中元素的最大值及其所在的行列下标值
/*
题目描述:按如下函数原型编程从键盘输入一个m行n列的二维数组,
然后计算数组中元素的最大值及其所在的行列下标值。其
中m和n的值由用户键盘输入。
已知m和n的值都不超过10。
相关知识(略)
输入
输入数组大小:"%d,%d"
下面输入数组中元素。
输出
输出格式:
数组大小输入提示信息:"Input m, n:"
数组元素输入提示信息:"Input %d*%d array: "
输出格式:"max=%d, row=%d, col=%d"
样例输入
5,5
1 2 3 4 5
4 5 6 100 2
3 2 1 5 6
1 2 3 5 4
3 5 6 4 8
样例输出
Input m, n:Input 5*5 array:
max=100, row=2, col=4
*/
#include<stdio.h>
int main(void)
{
/*********Begin*********/
int m, n;
scanf("%d,%d", &m, &n);
int a[m][n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
scanf("%d", &a[i][j]);
}
}
int max = a[0][0];
int row=0, col=0;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(max <= a[i][j]){
max = a[i][j];
row = i+1;
col = j+1;
}
}
}
printf("Input m, n:Input %d*%d array:\n", m,n);
printf("max=%d, row=%d, col=%d", max,row,col);
/*********End**********/
return 0;
}
第4关 二分查找
# include<stdio.h>
# define m 1000
int main()
{
int a[m],n,b;
scanf("%d",&b);
for(n=0;n<b;n++){
scanf("%d",&a[n]);
}
int find;
scanf("%d",&find);
if(b==1){
if(find==a[0]){
printf("1");
}
}
for(n=0;n<(b/2);n++) {
if (find == a[n]) {
printf("%d", n + 1);
break;
}
}
if(find!=a[n]) {
for (n = (b / 2); n < b; n++) {
if (find == a[n]) {
printf("%d", n + 1);
break;
}
}
}
if(find!=a[n]){
printf("None");
}
return 0;
}
第5关 鞍点
#define N 10
#include <stdio.h>
int Maxcol(int a[][N],int n,int row){
int i,maxcol=0;
for(i=1;i<n;i++)
if (a[row][i]>a[row][maxcol]) maxcol=i;
return maxcol;
}
int Minrow(int a[][N],int m,int col){
int i,minrow=0;
for(i=1;i<m;i++)
if (a[i][col]<a[minrow][col]) minrow=i;
return minrow;
}
int main(){
int m,n,i,j;
int maxcol,minrow;
int a[N][N];
scanf("%d %d",&m,&n);
for(i=0;i<m;i++) for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
for(i=0;i<m;i++){
maxcol=Maxcol(a,n,i);
minrow=Minrow(a,m,maxcol);
if (i==minrow){
printf("Array[%d][%d]=%d\n",i,maxcol,a[i][maxcol]);
break;
}
}
if(i>=m) printf("None\n");
}
第6关 删除最大值
#include<stdio.h>
int main(void)
{
int a[10];
int b[9];
for(int i = 0; i < 10; i++){
scanf("%d", &a[i]);
}
int max = 0;
for(int i = 0; i < 10; i++){
if(a[i] > max){
max = a[i];
}
}
int n = 0;
for(int i = 0; i < 10; i++){
if(a[i] != max){
b[n] = a[i];
printf("%d ", b[n]);
n++;
}
}
return 0;
}
指针
第1关 用指针法输入12个整数,然后按每行4个数输出
#include<stdio.h>
int main(void)
{
int a[12];
int *p = a;
for(int i = 0; i < 12; i++){
scanf("%d", p++);
}
p = a;
for(int i = 0; i < 12; i++){
if((i+1)%4==0){
printf("%d", *(p+i));
printf("\n");
}
else printf("%d ", *(p+i));
}
return 0;
}
第2关 指针变量作为函数参数实现两变量交换值
#include<stdio.h>
/*********Begin*********/
void exchange(int *a,int *b){
printf("%d %d",*b, *a);
}
/*********End**********/
int main(void)
{
int a,b;
scanf("%d%d",&a,&b);
/*********Begin*********/
exchange(&a,&b);
/*********End**********/
return 0;
}
第3关 报数
#include<stdio.h>
int main()
{
int n,a[1000];
int i,j=1,k=0,m=1;
scanf("%d",&n);
for(i=1;i<=n;i++)
a[i]=i;
while(k<n-1)
{
for(i=1;i<=n;i++)
{
for(j=m;j<=3;)
{
if(a[i]!=0)
{
a[i]=j;
m++;
if(m==4)
{
m=1;
}
}
break;
}
if(a[i]==3)
{
a[i]=0;
k++;
}
}
}
for(i=1;i<=n;i++)
{
if(a[i]!=0)
printf("%d",i);
}
}
第4关 strcmp函数
#include<stdio.h>
int strcmp(char *p1, char *p2)
{
int t;
for (; *p1!='\0'||*p2!='\0'; p1++, p2++)
if (*p1!=*p2){
t=*p1-*p2;
break;
}
if (*p1=='\0'&&*p2=='\0')
t=0;
return t;
}
int main(void)
{
char a[110],b[110];
scanf("%s%s",a,b);
if(strcmp(a,b)>0)
printf("%s", a);
else
printf("%s", b);
return 0;
}
图
第1关 实现图的宽度优先遍历
//Graph
///////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Graph.h"
/////////////////////////////////////////////////////////////
Graph* Graph_Create(int n)
{
Graph* g=(Graph*)malloc(sizeof(Graph));
g->n=n;
g->vetex=(char**)malloc(sizeof(char*)*n);
int i;
for (i=0; i<n; i++) g->vetex[i] = NULL;
g->adj=(int*)malloc(sizeof(int)*n*n);
int j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
g->adj[i*n+j]=0;
}
}
return g;
}
void Graph_Free(Graph* g)
{
free(g->adj);
int i;
for (i=0; i<g->n; i++) free(g->vetex[i]);
free(g->vetex);
free(g);
}
int Graph_WidthFirst(Graph*g, int start, Edge* tree)
//从start号顶点出发宽度优先遍历,(编号从0开始)
//返回访问到的顶点数,
//tree[]输出遍历树
//返回的tree[0]是(-1, start),
//真正的遍历树保存在tree[1..return-1], return是返回值
//顶点的访问次序依次为tree[0].to, tree[1].to, ..., tree[return-1].to
//输入时,tree[]的长度至少为顶点数
//返回值是从start出发访问到的顶点数
{
const int MAX=1000;
Edge queue[MAX];
int head=0, tail=0;
#define In__(a,b) {queue[tail].from=a; queue[tail].to=b; tail=(tail+1)%MAX;}/////////
#define Out__(a,b) {a=queue[head].from; b=queue[head].to; head=(head+1)%MAX;}//
#define QueueNotEmpty (head!=tail?1:0)///////////////////////////////////
#define HasEdge(i,j) (g->adj[(i)*g->n+(j)]==1)
char* visited=(char*)malloc(sizeof(char)*g->n);
memset(visited, 0, sizeof(char)*g->n);
int parent=-1;
int curr=start;
In__(parent, curr);
int k=0; //已经访问的结点数
/*请在BEGIN和END之间实现你的代码*/
/*****BEGIN*****/
while (QueueNotEmpty) {
Out__(parent, curr);
if (visited[curr]) continue;
visited[curr]=1;
tree[k].from=parent; tree[k].to=curr; k++;
int j;
for (j=0; j<=g->n-1;j++) {
if (HasEdge(curr,j) && !visited[j])In__(curr,j);
}
}
/*****END*******/
return k;
#undef In__//////////////////////////////
#undef Out__///////////////////////////////
#undef QueueNotEmpty////////////////////////
#undef HasEdge
}
第2关 实现图的深度优先遍历
//Graph
///////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Graph.h"
/////////////////////////////////////////////////////////////
Graph* Graph_Create(int n)
{
Graph* g=(Graph*)malloc(sizeof(Graph));
g->n=n;
g->vetex=(char**)malloc(sizeof(char*)*n);
int i;
for (i=0; i<n; i++) g->vetex[i] = NULL;
g->adj=(int*)malloc(sizeof(int)*n*n);
int j;
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
g->adj[i*n+j]=0;
}
}
return g;
}
void Graph_Free(Graph* g)
{
free(g->adj);
int i;
for (i=0; i<g->n; i++) free(g->vetex[i]);
free(g->vetex);
free(g);
}
int Graph_DepthFirst(Graph*g, int start, Edge* tree)
//从start号顶点出发深度优先遍历,(编号从开始)
//返回访问到的顶点数,
//tree[]输出遍历树
//返回的tree[0]是(-1, start),
//真正的遍历树保存在tree[1..return-1], return是返回值
//顶点的访问次序依次为tree[0].to, tree[1].to, ..., tree[return-1].to
//输入时,tree[]的长度至少为顶点数
//返回值是从start出发访问到的顶点数
{
/*请在BEGIN和END之间实现你的代码*/
/*****BEGIN*****/
/*请在BEGIN和END之间实现你的代码*/
/*****BEGIN*****/
const int MAX=1000;
Edge stack[MAX];
int top=-1;
#define Push__(a,b) {top++; stack[top].from=a; stack[top].to=b;}////
#define Pop__(a,b) {a=stack[top].from; b=stack[top].to; top--;}///////
#define StakNotEmpty (top>=0?1:0)////
#define HasEdge(i,j) (g->adj[(i)*g->n+(j)]==1)
char* visited=(char*)malloc(sizeof(char)*g->n);
memset(visited, 0, sizeof(char)*g->n);
int parent=-1;
int curr=start;
Push__(parent, curr);
int k=0; //已经访问的结点数
while (StakNotEmpty) {
Pop__(parent, curr);
if (visited[curr]) continue;
visited[curr]=1;
tree[k].from=parent; tree[k].to=curr; k++;
int j;
for (j=g->n-1; j>=0; j--) {
if (HasEdge(curr,j) && !visited[j]) Push__(curr,j);
}
}
free(visited);
return k;
#undef Push__////////////
#undef Pop__///////////////
#undef StakNotEmpty//////////////
#undef HasEdge
/*****END*******/
/*****END*******/
}
树
第1关 由双遍历序列构造二叉树
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ConstructTree.h"
/*
InPreToTree(): 由前序遍历序列和中序遍历序列构造二叉树
前序序列为pa[p1:p2]
中序序列为ia[i1:i2]
返回所构造的二叉树的根指针
*/
TNode* InPreToTree(char *pa, char *ia, int p1, int p2, int i1, int i2)
{
/*请在BEGIN和END之间实现你的代码*/
/*****BEGIN*****/
TNode *root=new TNode;
root->data=pa[p1];
root->left=NULL;
root->right=NULL; //递归终止条件:先序遍历中只有一个结点
if(pa[p1]==pa[p2])
return root;
//数组元素名是其首地址
int a=i1;
while(ia[a]!=root->data&&a<=i2) //中序里面
a++;
if(ia[a]!=root->data) //数组2遍历完成
exit(0);
int leftlen=a-i1;
if(leftlen>0) //左子树的个数
root->left=InPreToTree(pa,ia,p1+1,p1+leftlen,i1,a-1);
int rightlen=i2-a;
if(rightlen>0)
root->right=InPreToTree(pa,ia,p2-rightlen+1,p2,a+1,i2);
return root;
/******END******/
/*请不要修改[BEGIN,END]区域外的代码*/
}
void PrintPostTravel(TNode* t)
{
if(t==NULL) return;
if(t->left) PrintPostTravel(t->left);
if(t->right) PrintPostTravel(t->right);
printf("%c", t->data);
}
void DeleteTree(TNode* t)
{
if(t==NULL) return;
if(t->left) DeleteTree(t->left);
if(t->right) DeleteTree(t->right);
delete t;
}
第2关 打印二叉树
///////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "PrintTree.h"
/////////////////////////////////////////////////////////////
/*=================================================
函数:TNode* LayersToTree(char *A, int n)
功能:由补充虚结点(‘^’)的层序序列构造二叉树
参数:A: 补充了虚结点(‘^’)的层序序列
n: 序列的长度
输出: 所构造的二叉树的根指针,NULL表示没有构造出二叉树
==================================================*/
TNode* LayersToTree(char *A, int n)
{
TNode** pnode;
TNode* node;
int i;
if(n<=0)
return NULL;
pnode= new TNode*[n];
for(i=0; i<n; i++){
if(A[i]!='^'){
node=new TNode;
node->data=A[i];
node->left=NULL;
node->right=NULL;
pnode[i]=node;
}
else
pnode[i]=NULL;
}
for(i=0; i<n; i++){
if(pnode[i]==NULL) continue;
if(2*(i+1)<=n && pnode[2*(i+1)-1]!=NULL)
pnode[i]->left=pnode[2*(i+1)-1];
if(2*(i+1)+1<=n && pnode[2*(i+1)]!=NULL)
pnode[i]->right=pnode[2*(i+1)];
}
node=pnode[0];
delete pnode;
return node;
}
void PrintTreeRootLeft(TNode* r, int layer)
//r是树中一棵子树的根,打印以结点r为根的子树,
//layer是r在树中所处的层,约定树的根结点的层号为1
{
/*请在BEGIN和END之间实现你的代码*/
/*****BEGIN*****/
const int W=5;
int i,j;
if (r==NULL) return;
PrintTreeRootLeft(r->right, layer+1);
for(i=1; i<layer; i++) {
for (j=0;j<W;j++) printf("%c", '-');
}
for (j=0; j<W-1; j++) printf("%c",'-');
printf("%c\n", r->data);
PrintTreeRootLeft(r->left, layer+1);
/******END******/
/*请不要修改[BEGIN,END]区域外的代码*/
}
void DeleteTree(TNode* t)
{
if(t==NULL) return;
if(t->left) DeleteTree(t->left);
if(t->right) DeleteTree(t->right);
delete t;
}
计算表达式
第1关 栈的应用 - 计算中缀表达式
/**********************************************************
date: July 2017
copyright: Zhu En(祝恩)
DO NOT distribute this code.
**********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "LnkStack.h"
#include "Infix.h"
//////////////////////////////////////////////////////////////
void compute(LinkStack* so, LinkStack* sd)
//++++++++++++++++++++++++++++++++++++++++++++++
//so 运算符栈
//sd 操作数栈
//1 从运算符栈出栈一个运算符
//2 从操作数栈出栈两个操作数
//3 用出栈的运算符对出栈的操作数进行运算
//4 将运算结果进操作数栈
//+++++++++++++++++++++++++++++++++++++++++++++++
{
T a,b,c,d;
LS_Pop(so,c);
LS_Pop(sd,a);
LS_Pop(sd,b);
if (c=='*') d=b*a;
else if (c=='/') d=b/a;
else if (c=='+') d=b+a;
else if (c=='-') d=b-a;
else printf("never occur!");
LS_Push(sd, d);
}
double ComputeInfix(char* s)
{
// 请在此添加代码,补全函数ComputeInfix,计算中缀表达式
/********** Begin *********/
int i=0;
LinkStack* so=LS_Create();
LinkStack* sd=LS_Create();
while(s[i]) {
if ('0'<=s[i] && s[i]<='9') {
LS_Push(sd, s[i++]-48);
continue;
}
if(s[i]=='('||LS_IsEmpty(so)) {
LS_Push(so, s[i++]);
continue;
}
if(s[i]==')') {
T topitem;
while(LS_Top(so,topitem) && topitem !='(' )
compute(so, sd);
LS_Pop(so,topitem);
i++;
continue;
}
if(s[i]=='*'||s[i]=='/') {
T c;
LS_Top(so,c);
if (c=='*' || c=='/')
compute(so, sd);
LS_Push(so, s[i++]);
continue;
}
if(s[i]=='+'||s[i]=='-') {
T topitem;
while(LS_Top(so,topitem) && topitem !='(' )
compute(so, sd);
LS_Push(so, s[i++]);
continue;
}
}
while(!LS_IsEmpty(so))
compute(so, sd);
T res;
LS_Top(sd,res);
LS_Free(so);
LS_Free(sd);
return res;
/********** End **********/
}
第2关 栈的应用 - 计算后缀表达式
/**********************************************************
date: July 2017
copyright: Zhu En
DO NOT distribute this code.
**********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "LnkStack.h"
#include "Postfix.h"
double ComputePostfix(char* s)
{
// 请在此添加代码,补全函数ComputePostfix,计算后缀表达式
/********** Begin *********/
LinkStack* sd=LS_Create();
int i=0;
T k,top1,top2;
while(s[i]) {
switch (s[i]) {
case '+':
LS_Pop(sd,top1);
LS_Pop(sd,top2);
k=top1+top2;
LS_Push(sd,k);
break;
case '-':
LS_Pop(sd,top1);
LS_Pop(sd,top2);
k=top2-top1;
LS_Push(sd,k);
break;
case '*':
LS_Pop(sd,top1);
LS_Pop(sd,top2);
k=top1*top2;
LS_Push(sd,k);
break;
case '/':
LS_Pop(sd,top1);
LS_Pop(sd,top2);
k=top2/top1;
LS_Push(sd,k);
break;
default:
LS_Push(sd, (int)(s[i]-48));
}
i++;
}
T res;
LS_Top(sd,res);
LS_Free(sd);
return res;
/********** End **********/
}
字符串匹配
第1关 实现朴素的字符串匹配
int FindSubStr(char* t, char* p)
/*
从字符串t查找子字符串p。
字符串以数值结尾,例如p="str",那么p[0]='s',p[1]='t',p[2]='r',p[3]=0。
采用朴素的匹配算法,返回子字符串第一次出现的位置,例如t="string ring",p="ring",则返回2。
若没有找到,则返回-1。
*/
{
// 请在此添加代码,补全函数FindSubStr
/********** Begin *********/
int i=0, j=0;
while(p[i]!=0 && t[j]!=0) {
if (p[i]==t[j]) {
i ++;
j ++;
}
else {
j = j-i+1;
i = 0;
}
}
if (p[i] == 0) return j-i;
else return -1;
/********** End **********/
}
第2关 实现KMP字符串匹配
/*************************************************************
date:
copyright: Zhu En
DO NOT distribute this code without my permission.
**************************************************************/
//字符串 实现文件
//////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include "kmp.h"
/////////////////////////////////////////////////////
void KmpGenNext(char* p, int* next)
//生成p的next数组, next数组长度大于等于字符串p的长度加1
{
next[0]= -1;
int k= -1;
for (int i=1; p[i-1]!=0; i++)
{
while(k>=0&&p[k]!=p[i-1]) k=next[k];
k=k+1;
if (p[i]==p[k]) next[i]=next[k];
else next[i]=k;
}
}
int KmpFindSubWithNext(char* t, char* p, int* next)
//从t中查找子串p的第一次出现的位置
//若找到,返回出现的位置,否则返回-1
{
int i=0, j=0;
while(p[i]!=0 && t[j]!=0) {
if(p[i]==t[j]) {
i++;
j++;
}
else if (next[i]>=0) {
i = next[i];
}
else {
i=0;
j++;
}
}
if(p[i]==0) return j-i; //found
else return -1; //not found
}
队列
第1关 实现一个顺序存储的队列
#include <stdio.h>
#include <stdlib.h>
#include "SeqQueue.h"
SeqQueue* SQ_Create(int maxlen)
// 创建顺序队列, 队列最多存储maxlen个队列元素
{
SeqQueue* sq=(SeqQueue*)malloc(sizeof(SeqQueue));
sq->data=(T*)malloc(sizeof(T)*(maxlen+1));
sq->front=sq->rear=0;
sq->max=maxlen+1;
return sq;
}
void SQ_Free(SeqQueue* sq)
// 释放队列空间,以删除队列
{
free(sq->data);
free(sq);
}
void SQ_MakeEmpty(SeqQueue* sq)
// 将队列置空
{
sq->front=0;
sq->rear=0;
}
bool SQ_IsEmpty(SeqQueue* sq)
// 判断队列是否为空,为空返回true,否则返回false。
{
return sq->front==sq->rear;
}
bool SQ_IsFull(SeqQueue* sq)
// 判断队列是否为满。为满返回true,否则返回false。
{
return (sq->rear+1)%sq->max==sq->front;
}
int SQ_Length(SeqQueue* sq)
// 队列长度
{
return (sq->rear-sq->front+sq->max)%sq->max;
}
bool SQ_In(SeqQueue* sq, T x)
// 将x入队。若入队失败(队列满),则返回false,否则返回true。
{
if(SQ_IsFull(sq))
{
return false;
}
else
{
T* head=sq->data;
head[sq->rear]=x;
sq->rear=(sq->rear+1)%sq->max;
return true;
}
}
bool SQ_Out(SeqQueue* sq, T& item)
// 从队列sq出队一个元素,返回时item为出队的元素的值。若出队成功(队列不为空),则返回true,否则(队列空),返回false,此时item不会返回有效值。
{
if(SQ_IsEmpty(sq))
{
return false;
}
else
{
T* head=sq->data;
item=head[sq->front];
sq->front=(sq->front+1)%sq->max;//记得加sq->不要疏忽大意
return true;
}
}
bool SQ_Head(SeqQueue* sq, T& head)
// 获取队列头结点元素,返回时head保存头结点元素。
// 若获取失败(队列空),则返回值为false,否则返回值为true。
{
if ( SQ_IsEmpty(sq) )
{
return false;
}
else
{
head = sq->data[sq->front];
return true;
}
}
void SQ_Print(SeqQueue* sq)
// 依次打印出队列中的每个元素
{
int i=sq->front;
if (SQ_IsEmpty(sq))
{
printf("queue is emtpy");
return;
}
for (i=sq->front; i!=sq->rear; i=(i+1)%sq->max)
{
printf("%d ", sq->data[i]);
}
printf("\n");
}
第2关 实现一个链接存储的队列
#include <stdio.h>
#include <stdlib.h>
#include "CLnkQueue.h"
LNode* CLQ_Create()
// 创建一个队列
{
LNode* rear=(LNode*)malloc(sizeof(LNode));
rear->data = 0;
rear->next = rear;
return rear;
}
void CLQ_Free(LNode* rear)
// rear指向尾结点
{
CLQ_MakeEmpty(rear);
free(rear);
}
void CLQ_MakeEmpty(LNode* & rear)
// rear指向尾结点
// 将队列变为空队列
{
T item;
while(!CLQ_IsEmpty(rear))
CLQ_Out(rear,item);
}
bool CLQ_IsEmpty(LNode* rear)
// 判断队列是否为空
{
// 请在这里补充代码,完成本关任务
return rear->next->data==0;
//return rear->next->next==rear->next;
}
int CLQ_Length(LNode* rear)
// 返回队列长度,rear指向尾结点
{
// 请在这里补充代码,完成本关任务
return rear->next->data;
}
void CLQ_In(LNode* & rear, T x)
// 入队列, 新结点加入链表尾部。rear指向尾结点
{
// 请在这里补充代码,完成本关任务
LNode*node=(LNode*)malloc(sizeof(LNode));
node->data=x;
node->next=rear->next;
rear->next=node;
rear=node;
rear->next->data++;
}
bool CLQ_Out(LNode* & rear, T& item)
// 出队列。空队列时,返回值为false。rear指向尾结点
{
if(CLQ_IsEmpty(rear)){
return false;
}
if(rear->next->next==rear){
LNode*node=rear;
item=rear->data;
rear->next->next=rear->next;
rear=rear->next;
free(node);
}else{
item=rear->next->next->data;
LNode*node=rear->next->next;
rear->next->next=node->next;
free(node);
}
rear->next->data--;
return true;
}
bool CLQ_Head(LNode* rear, T& item)
// rear指向尾结点
// 获取队列头。空队列时返回值为false。
{
if (CLQ_IsEmpty(rear))
return false;
item = rear->next->next->data;
return true;
}
void CLQ_Print(LNode* rear)
// 打印队列
{
if (CLQ_IsEmpty(rear)) {
printf("The queue is: empty. \n");
return;
}
LNode* node=rear->next->next;
do {
printf("%d ", node->data);
node = node->next;
} while (node != rear->next);
//printf("\n");
}
栈
第1关 顺序存储的栈
#include <stdio.h>
#include <stdlib.h>
#include "SeqStack.h"
/*创建一个栈*/
SeqStack* SS_Create(int maxlen)
{
SeqStack* ss=(SeqStack*)malloc(sizeof(SeqStack));
ss->data=(T*)malloc(maxlen*sizeof(T));
ss->top=-1;
ss->max=maxlen;
return ss;
}
/*释放一个栈*/
void SS_Free(SeqStack* ss)
{
free(ss->data);
free(ss);
}
/*清空一个栈*/
void SS_MakeEmpty(SeqStack* ss)
{
ss->top=-1;
}
bool SS_IsFull(SeqStack* stack)
// 判断栈是否为满。为满返回true,否则返回false。
{
return stack->top+1>=stack->max;
}
bool SS_IsEmpty(SeqStack* stack)
// 判断栈是否为空。为空返回true,否则返回false。
{
return stack->top<0;
}
int SS_Length(SeqStack* stack)
// 获取栈元素个数
{
return stack->top+1;
}
bool SS_Push(SeqStack* stack, T x)
// 将元素x进栈,若满栈则无法进栈,返回false,否则返回true
{
if (SS_IsFull(stack))
{
return false;
}
stack->top++;
stack->data[stack->top]=x;
return true;
}
bool SS_Pop(SeqStack* stack, T &item)
// 出栈的元素放入item。若出栈成功(栈不为空),则返回true;否则(空栈),返回false。
{
if (SS_IsEmpty(stack))
{
return false;
}
item = stack->data[stack->top];
stack->top--;
return true;
}
/*获取栈顶元素放入item中,空栈则返回false*/
bool SS_Top(SeqStack* ss, T & item)
{
if (SS_IsEmpty(ss))
{
return false;
}
item = ss->data[ss->top];
return true;
}
/*从栈底到栈顶打印出所有元素*/
void SS_Print(SeqStack* ss)
{
if (SS_IsEmpty(ss))
{
printf("stack data: Empty!\n");
return;
}
printf("stack data (from bottom to top):");
int curr=0;
while(curr<=ss->top)
{
printf(" %d", ss->data[curr]);
curr++;
}
//printf("\n");
}
第2关 实现一个链接存储的栈
#include <stdio.h>
#include <stdlib.h>
#include "LnkStack.h"
/*创建栈*/
LinkStack* LS_Create()
{
LinkStack* ls=(LinkStack*)malloc(sizeof(LinkStack));
ls->top = NULL;
ls->len = 0;
return ls;
}
/*释放栈*/
void LS_Free(LinkStack* ls)
{
LNode* curr = ls->top;
while(curr)
{
LNode* next = curr->next;
free(curr);
curr=next;
}
free(ls);
}
/*将栈变为空栈*/
void LS_MakeEmpty(LinkStack* ls)
{
LNode* curr = ls->top;
while(curr)
{
LNode* next = curr->next;
free(curr);
curr=next;
}
ls->top = NULL;
ls->len = 0;
}
/*判断栈是否为空*/
bool LS_IsEmpty(LinkStack* ls)
{
return ls->len == 0;
}
/*获取栈的长度*/
int LS_Length(LinkStack* ls)
{
return ls->len;
}
/*将x进栈*/
void LS_Push(LinkStack* ls, T x)
{
LNode* node=(LNode*)malloc(sizeof(LNode));
node->data=x;
node->next=ls->top;
ls->top = node;
ls->len ++;
}
/*出栈。出栈元素放入item;如果空栈,将返回false*/
bool LS_Pop(LinkStack* ls, T& item)
{
LNode* node=ls->top;
if (node==NULL)
{
return false;
}
item = node->data;
ls->top = node->next;
ls->len --;
free(node);
return true;
}
/*读栈顶元素放入item。如果空栈,将返回false*/
bool LS_Top(LinkStack* ls, T& item)
{
LNode* node=ls->top;
if (node==NULL)
{
return false;
}
item = node->data;
return true;
}
/*从栈顶到栈底打印各结点数据*/
void LS_Print(LinkStack* ls)
{
if (ls->len==0)
{
printf("The stack: Empty!");
return;
}
printf("The stack (from top to bottom):");
LNode* curr=ls->top;
while(curr)
{
printf(" %d", curr->data);
curr=curr->next;
}
// printf("\n");
}
更多推荐
所有评论(0)