資料結構:字串(堆)——基本操作
阿新 • • 發佈:2018-11-14
資料結構的重要行不言而喻,簡單介紹我在這部分遇到的一些問題,希望對大家有少許幫助。
首先實現的多個操作:
程式碼:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define OK 1
#define ERROR -1
#define OVERFLOW -3
#define BIG 2
#define EQUAL 0
#define LITTLE -2
typedef int Status;
typedef struct
{
char *ch;
int length;
}HString;
//功能
void menu()
{
printf("\t\t***************串的堆實現*********************\n");
printf("\t\t\t1 求字串的長度\n");
printf("\t\t\t2 從主串中提取一個子串\n");
printf("\t\t\t3 比較兩個字串的大小\n");
printf("\t\t\t4 求一個子串在主串中的位置\n");
printf("\t\t\t5 將兩個字串連線成一個新的字串\n");
printf("\t\t\t0 退出系統\n" );
printf("\t\t***************順序棧實現*********************\n");
}
//初始化字串
Status StrAssign(HString &T,char * chars)
{
int len=0;
char *c;
if(T.ch)
free(T.ch);
//len=(int)strlen(chars)-1;
for(c = chars; *c; ++c)
len++;
if(!len)
{
T.ch=NULL;
T.length=0;
}
else
{
if (!(T.ch=(char *)malloc(len*sizeof(char))))
exit(OVERFLOW);
for(int j=0;j<len;j++)
{
T.ch[j]=chars[j];
}
T.length=len;
}
return OK;
}
//清空函式
Status ClearString(HString &S)
{
if(S.ch)
{
free(S.ch);
S.ch=NULL;
}
S.length=0;
return OK;
}
//求長度
int StrLength(HString S)
{
return S.length;
}
//求子串(第pos個位置,長度為len的子串,SubS拿來裝子串)
Status SubString(HString S,HString &SubS,int pos,int len)
{
if(pos<1 || pos>S.length || len<0 || len>S.length-pos+1)
return ERROR;
if(SubS.ch)
free(SubS.ch);
if(len==0)
{
SubS.ch=NULL;
SubS.length=0;
}
else
{
SubS.ch=(char*)malloc(len*sizeof(char));
for(int i=0;i<len;i++)
{
SubS.ch[i]=S.ch[pos-1];
pos++;
}
SubS.length=len;
}
return OK;
}
/*比較也可以寫成這個(避免我的警告)
//功能:對2個字串str1和str2逐一進行比較,如果對應位置相等,
// 繼續比較下一個字元,否則返回對應位置字元的ASCII的差值
int StrCompare(HString str1, HString str2)
{
int i;
for(i = 0;(i < str1.length && i < str2.length); i++) //2個字串存在從第一個開始的若干相等字串,則比較
{
if(str1.str[i]!=str2.str[i])
return(str1.str[i] - str2.str[i]);
}
return (str1.length-str2.length); //當上面比較完都沒發現不同字元時,此時比較串長
}
*/
//比較兩個字串的大小(應該可以優化)
int StrCompare(HString S,HString H)
{
int time;
time=0;
if(S.length>H.length)
return BIG;
if(S.length<H.length)
return LITTLE;
if(S.length==H.length)
{
for(int i=0;i<S.length;i++)
{
if(S.ch[i]>H.ch[i])
return BIG;
if(S.ch[i]<H.ch[i])
return LITTLE;
if(S.ch[i]==H.ch[i])
time++;
}
if(time==S.length)
return EQUAL;
}
}
//求一個字串在主串中的位置(要引用上面求子串的函式,書上用pos的意義是從第幾個位置起(有多個擷取後相等情況時)
int SubStringLocation(HString S,HString T)
{
int i=0;
HString SubS;//用來擷取的子串串
SubS.ch=NULL;
SubS.length=0;
while(i<S.length-T.length+1)//擷取位置起的後面一截
{
SubString(S,SubS,i,T.length); //這裡注意3個串別寫混了
if(StrCompare(T,SubS)!=EQUAL)
{
i++;
if(i==S.length-T.length+1-1) //防止123456aaafffg fffffff
return ERROR;
}
else
return i; //如果有多個子串,存入陣列中輸出陣列即可
}
}
//連線兩個字串為一個字串
Status StringCat(HString &T,HString S,HString S2)
{
if(T.ch)
free(T.ch);
if(!(T.ch=(char *)malloc((S.length+S2.length)*sizeof(char))))
exit(OVERFLOW);
for(int i=0;i<S.length;i++)
{
T.ch[i]=S.ch[i];
}
T.length=S.length+S2.length;
for( i=S.length;i<T.length;i++)
{
T.ch[i]=S2.ch[i-S.length];//注意別寫漏掉i-S.length
}
return OK;
}
int main()
{
int choice,pos=0,len=0;
HString S,T,Str;
S.ch=NULL;
S.length=0;
T.ch=NULL; //注意必須先初始化,不然沒有值輸出
T.length=0;//注意必須先初始化
Str.ch=NULL;
Str.length=0;
char s[100],s1[100];
while(1)
{
menu();
printf("請輸入要選擇的功能:\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
{
printf("請輸入一個字串:\n");
scanf("%s",s);
if(StrAssign(T,s))
printf("字串長度為:%d\n",StrLength(T));
printf("請按回車繼續!\n");
getchar();getchar();
system("cls");break;
}
case 2:
{
printf("請輸入主串:\n");
scanf("%s",s);
if(StrAssign(S,s))
{
printf("請輸入提取子串的位置pos,以及長度len:");
scanf("%d%d",&pos,&len);
ClearString(T);//注意釋放,防止再次輸入
if(SubString(S,T,pos,len)==OK) //這裡為什麼要寫OK才行?
{
for(int i=0;i<T.length;i++)
{
printf("%c",*(T.ch+i));//指標
}
printf("\n");
}
else
printf("輸入的位置或長度有誤!\n");
}
printf("請按回車繼續!\n");
getchar();getchar();
system("cls");break;
}
case 3:
{
printf("請輸入兩個字串s和s1:\n");
scanf("%s%s",s,s1);
if(StrAssign(S,s) && StrAssign(T,s1))
{
if(StrCompare(S,T)==BIG)
printf("字串s:%s更大",s);
if(StrCompare(S,T)==EQUAL)
printf("字串s:%s與字串s1: %s相等",s,s1);
if(StrCompare(S,T)==LITTLE)
printf("字串s1:%s更大",s1);
}
printf("請按回車繼續:\n");
getchar();getchar();
system("cls");break;
}
case 4:
{
printf("請輸入主串s:\n");
scanf("%s",s);
if(StrAssign(S,s))
{
printf("請輸入字串s1:\n");
scanf("%s",s1);
if(StrAssign(T,s1))
{
if(SubStringLocation(S,T)!=ERROR)
printf("子串s1在主串s中按從左往右計數的位置(只計算出第相同子串一個位置)為:%d\n",SubStringLocation(S,T));
else
printf("主串中沒有該子串!\n");
}
}
printf("請按回車繼續!\n");
getchar();getchar();
system("cls");break;
}
case 5:
{
printf("請輸入第一個字串s:\n");
scanf("%s",s);
if(StrAssign(S,s))
{
printf("請輸入第二個字串s1:\n");
scanf("%s",s1);
if(StrAssign(T,s1))
{
if(StringCat(Str,S,T))
{
for(int i=0;i<Str.length;i++)
printf("%c",*(Str.ch+i));
}
printf("\n");
}
}
printf("請按回車繼續!\n");
getchar();getchar();
system("cls");break;
}
case 0:printf("成功退出系統!\n");exit(0);break;
default:printf("輸入有誤!\n");exit(0);break;
}
}
return 0;
}
綜合程式是需要不斷改進的,下面說說我遇到的問題吧:
1.
這以上3中常見串問題 大家需要注意。
程式碼中大多數註釋都有,若有錯誤望大家不吝指教,祝大家程式設計愉快,謝謝!。