順序表的建立及使用
順序表: 就所謂的數組式操作
編程實現順序存儲結構中的基本操作的實現(電話本的建立、插入、刪除、修改、逆置、查找、輸出)
整個操作過於簡陋, 只對上述功能做敘述, 採用結構體數組實現, 本打算用class操作, 可因爲某種原因就擱置了………..
代碼中的註釋部分是用於測試數據, 電話本只存有number, name
//size全局變量表示電話本當前大小不包含0位置,0號位置作爲中間變量處理, 重新申請中間變量太麻煩了就省略
//
#include<cstdio>
#include<cstring>
#define MAXSIZE 100
#define null 0
int size=0; //表示當前電話本中有幾個聯繫人的信息
typedef struct{
char name[10];
char number[12];
}telephone;
telephone t[MAXSIZE];//創建結構體數組的時候,可採用new,此處對此操作省略
void create();
int find(int lo,int hi,telephone t[],char* target_value);
void insert(telephone t[],int size);
void display(telephone t[],int size);
void convert(telephone t[],int size);
void create(){
int t_size;
printf("輸入需要創建的電話本大小");
scanf("%d",&t_size);
insert(t,t_size+1);
// printf("%d\n",size);
}
int find(int lo,int hi,telephone t[],char target_value[]){//使用二分查找
if(lo>=hi)return null;//遞歸基
if(strcmp(target_value,t[(lo+hi)/2].name)==0) //遞歸基
return (lo+hi)/2;
if(strcmp(target_value,t[(lo+hi)/2].name)>0)
return find((lo+hi)/2+1,hi,t,target_value);
else if(strcmp(target_value,t[(lo+hi)/2].name)<0)
return find(lo,(lo+hi)/2,t,target_value);
}
//在插入的過程中使用插入排序,以便於find操作
void insert(telephone t[],int t_size){
int i,j;
for(i=size+1;i<t_size;i++){
printf("輸入姓名,電話\n");
scanf("%s%s",t[i].name,t[i].number);//t[0]爲哨兵,作爲每次插入的中間變量
strcpy(t[0].name,t[i].name);//哨兵元素每次表示要插入的元素(該元素先插到數組的尾部)
strcpy(t[0].number,t[i].number);
j=i-1;//此時的j表示待插入元素的前一個元素
//待插入的元素比哨兵元素小,進行移動覆蓋,查找到比哨兵元素小的值時
//將哨兵元素放到此位置
while((strcmp(t[j].name,t[0].name)>0)){
strcpy(t[j+1].name,t[j].name);
strcpy(t[j+1].number,t[j].number);
j--;
}
//此處的j指向剛插入的元素的位置
strcpy(t[j+1].name,t[0].name);//哨兵放置
strcpy(t[j+1].number,t[0].number);
++size; //每插入一個人的信息,size增加一次
// printf("當前i=%d insert後size=%d\n",i,size);
}
// printf("insert後size=%d\n",size);
return;
}
int remove(telephone t[],char* target_value,int t_size){
//在刪除的過程中出現,將局部變量的值的名稱設置了和全局變量一致,出現size無法減少的情況
int i;
int location=find(0,size,t,target_value);
// printf("find=%d\n",location);
if(location==0) return null;
for(i=location;i<=size;i++){
//將要刪除的元素進行覆蓋處理,令i=size,可實現將最後一個元素變爲"\0"
strcpy(t[i].name,t[i+1].name);
strcpy(t[i].number,t[i+1].number);
}
// strcpy(t[i].name,"\0");
// strcpy(t[i].number,"\0");//將要刪除的元素的name.number置爲空串
// if(location==size){//判斷是否刪除最後一個元素,若是則需要進行對0號元素更新,防止insert出現錯誤
// strcpy(t[0].name,t[i-1].name);
// strcpy(t[0].number,t[i-1].number);
//}
size--;
return location;
// printf("remove後size=%d\n",size);
}
void display(telephone t[],int size){
char c;
//可在display中引入倒置, 此處不做敘述
for(int i=1;i<=size;i++)
printf("%d=姓名:%s, 號碼:%s\n",i,t[i].name,t[i].number);
return;
}
void convert(telephone t[],int size){//倒置處理
for(int i=1;i<=size/2;i++){
strcpy(t[0].name,t[i].name);strcpy(t[i].name,t[size-i+1].name);strcpy(t[size-i+1].name,t[0].name);//name做倒置
strcpy(t[0].number,t[i].number);strcpy(t[i].number,t[size-i+1].number);strcpy(t[size-i+1].number,t[0].number);//number倒置
}
}
int main(){
int i,key=1;
char *c; //用於插入, 刪除時臨時的中間變量, 也可使用數組
while(key){
printf("1-創建電話本\n 2-插入賬戶信息\n 3-查找號碼\n 4-刪除號碼\n 5-查看所有信息\n 6-將電話本倒置\n 7-關閉\n");
scanf("%d",&i);
switch(i){
case 1:create();fflush(stdin);break;
if(create_flag==1){
case 2:insert(t,size+2);fflush(stdin);break;//當執行單步插入的時候形參要修改爲在size的基礎上擴大1,但是t[0]並不存數據,所以size+2處理
case 3:printf("輸入查找的元素,0表示查找失敗\n 查找的姓名:");scanf("%s",c);printf("所在的位置是%d\n",find(1,size,t,c));fflush(stdin);break;
case 4:printf("輸入要刪除的元素,0表示刪除失敗\n 刪除的姓名:");scanf("%s",c);printf("刪除元素的位置是%d\n",remove(t,c,size));fflush(stdin);break;
case 5:display(t,size);fflush(stdin);break;
case 6:convert(t,size);fflush(stdin);break;
}else printf("未創建電話本,不可刪除,查找,展示,倒置操作");
case 7: key=0;break;
}
}
return 0;
}
在寫代碼的過程中出現的問題是:
- 二分查找的時候沒有做尾遞歸處理,導致返回值出現問題, 不能正確的返回出是否查找到當前元素的位置, 處理find((lo+hi)/2+1,hi,t,target_value); 寫成做 (lo+hi)/2; 導致在遞歸查找的過程中出現死遞歸, 不能返回出來
- 在remove中將局部變量的名稱與全局變量的名稱寫成一樣的(size), 導致size–出錯; 真是愚蠢
- 進行代碼調試的時候只是從邏輯的角度分析問題, 而沒有寫printf語句觀察程序的運行過程, 細心考慮每個變量的變化情況, 造成無法準確地定位錯誤的位置