/*************************************************************
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;}voidSL_Free(SeqList* slist)// 释放/删除 顺序表// 与SqLst_Create()配对{free(slist->data);free(slist);}voidSL_MakeEmpty(SeqList* slist)// 置为空表{
slist->len=0;}intSL_Length(SeqList* slist)// 获取长度{return slist->len;}
bool SL_IsEmpty(SeqList* slist)// 判断顺序表是否空{return0==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];}}voidSL_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;}intSL_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;elsereturn-1;}intSL_DelValue(SeqList* slist, T x)// 删除第一个值为x的结点,// 存在值为x的结点则返回结点编号, 未找到返回-1{int i=SL_FindValue(slist, x);if(i>=0){SL_DelAt(slist, i);}return i;}voidSL_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;}voidLL_Free(LinkList* llist)// 释放链表的结点,然后释放llist所指向的结构。{
LinkNode* node=llist->front;
LinkNode* nextnode;while(node){
nextnode=node->next;free(node);
node=nextnode;}free(llist);}voidLL_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;}intLL_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;}intLL_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;}voidLL_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;}//当前位置为表头elseif(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;}elseif(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;}/* 删除的是表中或表尾结点*/elseif(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;}intLL_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;}}intLL_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;}voidLL_Print(LinkList* llist)// 打印整个线性表。{
LinkNode* node=llist->front;while(node){printf("%d ", node->data);
node=node->next;}printf("\n");}
函数
第1关 求和
#include<stdio.h>//编写函数/*********Begin*********/intsum1(int n){int sum =0;for(int i =1; i <= n; i++){
sum += i;}return sum;}/*********End**********/intmain(void){/*********Begin*********/int n =0;scanf("%d",&n);int sum =sum1(n);printf("%d", sum);/*********End**********/return0;}
第2关 回文数计算
#include<stdio.h>voidsolve(){/*********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**********/}intmain(void){solve();return0;}
第3关 编写函数求表达式的值
#include<stdio.h>//编写题目要求的函数/*********Begin*********/doublesum1(int n){double sum =1;if(n==1)return1;else{for(int i = n+1; i >=2; i--){// 为啥是n+1呢??因为下面这个公式是用n推导的
sum =1+(double)(((i-1)*sum)/(2*i-1));}return sum;}}/*********End**********/intmain(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**********/return0;}
第4关 阶乘数列
#include<stdio.h>//编写函数/*********Begin*********/voidsum1(int n){longlongint sum =1;if(n==1)printf("1");else{for(int i = n; i >=2; i--){
sum =1+ i*sum;}printf("%lld",sum);}}/*********End**********/intmain(void){/*********Begin*********/int n=0;scanf("%d",&n);sum1(n);/*********End**********/return0;}
第5关 亲密数
#include<stdio.h>// 求因子的函数 intsum(int n){int sum =0;for(int i =1; i <= n/2; i++){if(n%i ==0){
sum += i;}}return sum;}voidsolve(){/*********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**********/}intmain(void){solve();return0;}
第6关 公约公倍数
#include<stdio.h>//编写最大公约数GCD函数/*********Begin*********/longlongintGCD(longlongint a,longlongint b){longlongint max =1;for(longlongint i =1; i <= a; i++){if(a%i ==0&& b%i ==0){
max = i;}}return max;}/*********End**********///编写最小公倍数LCM函数/*********Begin*********/intLCM(int a,int b){}/*********End**********/intmain(void){longlongint a,b;/*********Begin*********/scanf("%lld %lld",&a,&b);if(a>b){longlongint temp = a;
a = b;
b = temp;}// a一直小于bif(a<0|| b <0){printf("Input Error");}else{longlongint max =GCD(a,b);longlongint min = a * b / max;printf("%lld %lld",max,min);}/*********End**********/return0;}
一维数组和二维数组
第1关 排序问题
#include<stdio.h>intmain(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**********/return0;}
第2关 查找整数
#include<stdio.h>intmain(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**********/return0;}
第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>intmain(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**********/return0;}
第4关 二分查找
#include<stdio.h>#definem1000intmain(){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");}return0;}
#include<stdio.h>intmain(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++;}}return0;}
指针
第1关 用指针法输入12个整数,然后按每行4个数输出
#include<stdio.h>intmain(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");}elseprintf("%d ",*(p+i));}return0;}
/**********************************************************
date: July 2017
copyright: Zhu En(祝恩)
DO NOT distribute this code.
**********************************************************/#include<stdio.h>#include<stdlib.h>#include"LnkStack.h"#include"Infix.h"//voidcompute(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;elseif(c=='/') d=b/a;elseif(c=='+') d=b+a;elseif(c=='-') d=b-a;elseprintf("never occur!");LS_Push(sd, d);}doubleComputeInfix(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"doubleComputePostfix(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关 实现朴素的字符串匹配
intFindSubStr(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;elsereturn-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"/voidKmpGenNext(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;}}intKmpFindSubWithNext(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++;}elseif(next[i]>=0){
i = next[i];}else{
i=0;
j++;}}if(p[i]==0)return j-i;//foundelsereturn-1;//not found}