是這樣子,這是在下的作業,作要要求如下:
讀進檔案,將檔案中的數字建成二元搜尋樹
印出樹的preorder
印出滿足特定範圍的資料,並由小排到大,比方說 BinTree.exe data.txt 3 100
程式要找出3~100之間的資料,並依序排出

請大家幫我寫嗎??這樣就太該打了
我根據要求寫了以下的程式碼,但是......compile過了,run的時候會出現本程式即將要關閉
不知道是不是我指標亂用??而且在cmd下執行什麼事情都沒有發生,對,他真的什麼都沒發生
想請在上的前輩指點迷津,看在下盲點在哪裡??請原諒我,在下還不太會寫註解
註解寫得有寫跟沒些差不多。另外,沒有縮排看的蠻辛苦的,所以我附上我的cpp檔跟測試資料

---------------------------------------------------------------------------
經過claud-wu大大的指正,在下更正,並更新附檔

剛剛找出部份問題,修正後已可執行,只是樹依然建立的不正確
目前發現在字串轉數字時沒轉好,繼續尋找



#include<iostream>
#include<fstream>
using namespace std;

#define MAX 100000

int lowbound=0, upbound=0;

struct TreeNode
{
struct TreeNode *left;
int data;
struct TreeNode *right;
};

class BinTree
{
public:
TreeNode *root;
BinTree(){root = NULL;}

void Preorder(TreeNode *node){ //preorder用遞迴作
if(node!=NULL){
cout << node->data << ",";<br>Preorder(node->left);
Preorder(node->right);
}
}

void Insert(int source){
TreeNode *ptr = new TreeNode;
ptr->data = source; //initial
ptr->left = NULL; //initial
ptr->right = NULL; //initial
if(root == NULL) //當跟節點為NULL的情況
root = ptr;
else{ //當跟節點不為NULL的情況
TreeNode *q = root;
if(source < q->data) //插入的資料比較小
q->left = ptr; //插到左邊
else
q->right = ptr;
}
}
};

int temp3[MAX]={0}; //temp3用來存符合上下界的資料
int a=0;
void Range(TreeNode *node, int low, int up)
{ //這是我用來搜尋符合上下界的副函式
if(node->data <low) //如果樹的值比範圍小
Range(node->right, low, up); //那左子樹就不看了,繼續搜尋右子樹
else if(node->data >= low && node->data <= up){//在範圍內
temp3[a++]=node->data; //把符合的值存到temp3的array中
Range(node->left, low, up); //繼續搜尋左子樹
Range(node->right, low, up); //繼續搜尋右子樹
}
}

void Sort() //請原諒我偷懶用氣泡 Orz
{
int i=0, j=0, k=0;
for(i=0; temp3[i]!='\0'; i++)
for(j=1; temp3[j]!='\0'; j++)
if(temp3[j] < temp3[j-1]){<br>k=temp3[j]; temp3[j]=temp3[j-1]; temp3[j-1]=k;
}
for(i=0; temp3[i]!='\0'; i++)
cout << temp3[i] << ",";<br>cout << ";" << endl;<br>}

int main(int argc, char *argv[])
{
BinTree MyTree;
ifstream ifile1;
ifile1.open(argv[1]);
char temp1[MAX]; //temp1是用來存讀進來的資料

int i=0, j=0, k=0;
char ch;
for(i=j=0; !ifile1.eof(); i++){ //開始把讀進的檔案存給temp1
ifile1.get(ch);
temp1[j++]=ch;
}
/*while(ifile1)
ifile1.read(temp1,MAX);*/
ifile1.close(); //關閉檔案

int temp2[MAX]={0}; //temp2用來存轉換成int後的資料
for(i=j=k=0; temp1[i]!='\0'; i++){
if(temp1[i]>='0' && temp1[i]<='9'){ //從字串轉成數字
for(j=i; temp1[j]!='\n'; j++) ; //尋找換行,執行atoi
temp2[k++]=atoi(&temp1[i]);
i=j;
}
}

/*for(i=j=0; temp1[i]!='\0'; i++){
if(temp1[i]=='\n') continue;
temp2[j++]=temp1[i];
}*/
int temp=0;
for(i=0; temp2[i]!='\0'; i++){
temp=temp2[i];
MyTree.Insert(temp); //插入資料到樹
}

if(argc == 2){ //當沒有給定範圍,也就是傳入的引數只有2個
MyTree.Preorder(MyTree.root); //呼叫preorder,印出資料
cout << ";" << endl;<br>}
if(argc == 4){ //有給定上下界,所以引數有4個
lowbound=atoi(argv[3]); //先把上、下界從char轉到int
upbound=atoi(argv[4]); //同上
Range(MyTree.root, lowbound, upbound); //依照上下界找出符合
Sort(); //再把符合的值排序印出
}
//char wait; cin >> wait;
return 0;
}

附加壓縮檔: 200712/mobile01-13f11cdc2f22b8c7a700c9284778aaf5.zip
我真的很閒...
幫你看了一下
仔細想想argv[1]跟"argv[1]"的差別...

加油, 至少是真正的++
不是魚目混珠的c + cin/cout
感謝claud-wu大大的指點,argv[1]才是正確的開檔

在下.....繼續尋找其他問題當中
奇蹟的公式等於萬千的努力加上絕不放棄
看了你的 insert function, 我有三個想法.
void Insert(int source)
{
TreeNode *ptr = new TreeNode;
ptr->data = source; //initial
ptr->left = NULL; //initial
ptr->right = NULL; //initial

if(root == NULL) //當跟節點為NULL的情況
root = ptr;
else{ //當跟節點不為NULL的情況
TreeNode *q = root;
if(source < q->data) //插入的資料比較小
q->left = ptr; //插到左邊
else
q->right = ptr;
}
}
};

1. 你確定可以 compile??? 你的 { 跟 } 數目根本對不起來, 兩個 { 卻有三個 }???
2. 當跟節點不為NULL的情況, 你把新 node 加在左或右, 請問本來在左或右的 node 跑哪去了???
3. 你的 if(source < q->data)... else... 會把資料大小相同的情況加到右邊, 你確定這是你要的嗎??
CMC-SkyWalker wrote:
1. 你確定可以 compile??? 你的 { 跟 } 數目根本對不起來, 兩個 { 卻有三個 }???
2. 當跟節點不為NULL的情況, 你把新 node 加在左或右, 請問本來在左或右的 node 跑哪去了???
3. 你的 if(source < q->data)... else... 會把資料大小相同的情況加到右邊, 你確定這是你要的嗎??


1.是可以compile的,但run好像真的有問題

2.這就是我建tree沒建好了,忘了考慮原本有的話該怎麼辦
經另一位網兄pm告之有發現問題

3.因為我們的資料都是不相同的,所以沒有考慮相同時的問題

其實上上星期已完成demo過了,在那位網兄pm指點後,已經點出大部分問題(就是tree建立的問題)
剩下的就是功能擴充了,只是忘了上來報告最後結果,最後還是很感謝CMC-SkyWalker兄指點
奇蹟的公式等於萬千的努力加上絕不放棄
不睡覺,跑來幫你debug,真糟糕

1.
你的insert函式寫得不好,應該是要可以遞迴的
要把指標放到函式參數,使insert函式能真正去選找正確的插入點
而不是你現在程式只和root數值比,比完就往root的左右塞
看程式,這個二元樹應該最多只能放三個值

因為只有root和左右三個值可以找出來
你在插入值的時候,沒有考慮到把原來存放在 right(left) 的記憶體位址複製到你要插入節點的 right(left)
且這作法不正確

應該要先找到最外(下)層的 node ,將你插入的 node 接在最外層 node 的指標下
此方式做出來的 tree 就是排序好的,不需要將搜尋的結果再次排序
但你的Range函式就要修正,以適用於此作法
56-60行要變更
else if(node->data >= low && node->data <= up){//在範圍內

Range(node->left, low, up); //繼續搜尋左子樹
temp3[a++]=node->data; //把符合的值存到temp3的array中
Range(node->right, low, up); //繼續搜尋右子樹
}

此修正可以將找出來的數值從最小排到最大
避免還要排序

2.
另一點,你在浪費 ifstream 的功能
宣告一個字元陣列
char str[10];

while(ifile1 >> str)
{
temp2[k++] = atoi(str);
}

上面的作法可以解決你目前先讀字元,抓換行符號,轉成int形態,最後存起來。
此外,data.txt 的數值分隔可以為空白或換行符號


希望你有所得
文章分享
評分
評分
複製連結

今日熱門文章 網友點擊推薦!