純粹只是一道C++題目,求錯誤分析

剛剛接觸《數據結構》於是想試著用單鏈表這一東東去做POJ的ACM1002題目,寫好了代碼,在我的VC下運行似乎也沒什麼結果上的錯誤,然而提交到網站後卻只有"wrong answer"的答案,苦苦的看了一個小時後並未發現什麼錯誤,又看不懂百度上此題目的其他解法。聽說知乎高手雲集,跪求高人指出錯誤之處,不勝感激

題目來源:http://poj.org/problem?id=1002
源碼:
#include &< iostream &>
#include &< string &>
using namespace std;

class data{ //定義一個DATA的類,實現單鏈表
public:
int cell[7]; //內容部分(電話號碼)
int i,count; /* i為data構造函數所需,count為記錄同一電話號碼的重複次數*/
data *next; //實現單鏈表的指針(不懂稱呼)
data(int _cell[],data *_next=NULL)//構造函數
{
for(i=0;i &< 7;i++ )
cell[i]=_cell[i];
next=_next;
count=1;
}
};

int compare(int a[],int b[])/*兩個號碼作比較,調入值為儲存電話號碼的兩個數組的地址,返回值是特定的『狀態結果』,其中返回值『0』代表號碼相同,返回值『1』代表取下個號碼與原號碼進行比較,返回值『1』代表插入原號碼 */
{
int l;
for(l=0;l &< 7;l++ )
{
if(a[l] &< b[l])
return -1;
if(a[l] &> b[l])
return 1;
}
return 0;
}

int main()
{
int n,j,k,m,t,temp[7],sum=0;
string str;
char output[9];
data *p=NULL;
data *p_temp=NULL;
data *p_temp_pre=NULL;
cin &> &> n;
for(j=0;j &< n;j++)

{
cin &> &> str;
m=0;
for(k=0;k &< str.size();k++)

{
if(str[k]=="-") /*現實字元到整形的轉換,包括實現各種大寫字母的轉換,除去『-』 */
continue;
else
{
if(str[k] &> ="0"str[k] &< ="9")
temp[m]=str[k]-"0";
else if(str[k] &> ="A"str[k] &< ="C")
temp[m]=2;
else if(str[k] &> ="D"str[k] &< ="F")
temp[m]=3;
else if(str[k] &> ="G"str[k] &< ="I")
temp[m]=4;
else if(str[k] &> ="J"str[k] &< ="L")
temp[m]=5;
else if(str[k] &> ="M"str[k] &< ="O")
temp[m]=6;
else if(str[k]=="P"..
str[k]=="R"..str[k]=="S") //此處的..為或的『雙豎』,因打不出那個符號!
temp[m]=7;
else if(str[k] &> ="T"str[k] &< ="V")
temp[m]=8;
else if(str[k] &> ="W"str[k] &< ="Y")
temp[m]=9;
m++ ;
}
}
if(p==NULL) //如果鏈表為空,創建
p=p_temp=new data(temp);
else //鏈表不為空
{
for(t=compare(temp,p_temp- &> cell);t==1;)
{
if(p_temp- &> next==NULL)
{
t=2; //『t=2』代表在鏈表最後一個元素的後面插入新元素
break;
}
p_temp_pre=p_temp;
p_temp=p_temp- &> next;
t=compare(temp,p_temp- &> cell);
}
if(t==-1) //插入動作
{
if(p_temp==p) //插入的新元素在鏈表的首部
p=new data(temp,p_temp);
else
p_temp_pre=new data(temp,p_temp);
}
if(t==0) //兩個號碼相同,count 1,不做插入
p_temp- &> count =+1;
if(t==2) //向尾端插入
p_temp- &> next=new data(temp);
p_temp=p;
}
}
while(p_temp!=NULL) //檢索元素和輸出
{
if(p_temp- &> count &> 1)
{
for(j=0;j &< 3;j++)
output[j]=p_temp- &> cell[j]+"0";
output[3]="-";
for(j=4;j &< =7;j++)
output[j]=p_temp- &> cell[j-1]+"0";
output[8]="";
sum++;
cout &< &< output &< &< " " &< &< p_temp- &> count &< &< endl;
}
p_temp=p_temp- &> next;
}
if(sum==0)
cout &< &< "No duplicates." &< &< endl;

return 0;
}



似乎知乎對" &< "和『 &> 』字元都會自動在其前後兩端加上空格的


看了一下你的代碼,很明顯的一個bug是插入:
if(t==-1) //插入動作
{
if(p_temp==p) //插入的新元素在鏈表的首部
p=new data(temp,p_temp);
else
p_temp_pre=new data(temp,p_temp);
}

p_temp_pre=new data(temp,p_temp);
改成
data* fix = new data(temp, p_temp);
p_temp_pre- &> next = fix;
應該能正確運行了。

但是你的代碼可讀性極差,基本沒有任何優化,對號碼的排序採用的是低效的插入排序(當然,既然選擇鏈表就無法利用qsort等其他方法了)而且還有嚴重內存泄露(每個new都要對應一個delete,不然就應該使用shared_ptr或者其他智能指針)。如果你是想要練習鏈表這個數據結構,就應該把鏈表實現的再抽象一點,比如做成模板類。這樣今後其他場合也可以用。不然為何用C++呢,直接用C實現好了。如果旨在解題,本題的最佳方法顯然是哈希表。還有其它的問題,比如數字和字母的對應完全可以寫成enum形式或者查表得到,會節約大量時間。
本題原為ACM北美賽99年的題目,可以在[1]處找到解答和測試數據。
另外,有些個人建議:1) 今後請不要使用「跪求」這個詞語,使用它會降低別人幫你解答的幾率,本主題就是證明。2) 請不要完全貼出代碼,這樣顯得你根本沒有調試過,正確的方法是首先自己調試,並給出你認為可能有問題的代碼及你的思考。
[1] http://www.ntnu.edu.tw/acm/ProblemSetArchive/B_US_EastCen/1999/index.html


推薦閱讀:

有哪些「上帝演算法」?
是否存在某種成熟的方法用較少的字元表示大量的信息?
500px的照片分數是怎麼算的?
小生境(Niche)機制是否可以用於處理SNS中的用戶群體相似性高的問題?
如何理解量子糾纏對量子演算法的影響?

TAG:演算法 | C | POJ | ACM競賽 |