Debugging binary search in a vector

I have some code where I am attempting to build a vector and keep it in order by name. When a new planet is added, I binary search by name and then slide everything to make room. If I add planets a, then c, then b it puts b at the beginning rather than in between a and c. after that, it seems to function well. I don't have access to a debugger, so it's been painful trying to figure it out. Any thoughts would be appreciated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#include <iostream>
#include "input.h"
#include <vector>
#include <string>
#include <cmath>

using namespace std;

const double G = 6.67408e-11;

class Planet
{
private:
	double radius;
	double mass;

public:
	Planet();
	string name;
	double SArea();
	double Density();
	double g();
	void Input();
	void Display();
	bool SetName(string n);
	bool SetRadius(double r);
	bool SetMass(double m);

};

void AddPlanet(vector<Planet>& l);
void DelPlanet(vector<Planet>& l);
void AddToList(vector<Planet>& l, Planet newp);
void ListAll(vector<Planet>& l);
void Remove(vector<Planet>& list, int idx);
bool BinSearch(vector<Planet>& l, string n, int& index);
int menu();




int main()
{
	vector<Planet> PList;
	int choice=0;
	do
	{
		choice=menu();
		if (choice==1)
		{
			AddPlanet(PList);
		}
		else if(choice==2)
		{
			DelPlanet(PList);
		}
		else if(choice==3)
		{
			int i=0;
			if(BinSearch(PList,ReadString("Planet Name? "), i)==false)
			{
				cout << "Planet not found" << endl;
			}	
			else
			{
				PList[i].Display();
			}
		}
		else if(choice==4)
		{
			ListAll(PList);
		}
		else 
		{
			cout<<"Goodbye"<<endl;
		}
	} while(choice!=5);
	return 0;
}
 
int menu()
{
	int rv=0;
	do
	{
		cout<<"1. Add Planet"<<endl;
		cout<<"2. Delete Planet"<<endl;
		cout<<"3. Search Planet"<<endl;
		cout<<"4. List All"<<endl;
		cout<<"5. Quit"<<endl;
		rv=ReadInt("Choose one of the above options");
	} while(rv<1||rv>5);
	return rv;
}


Planet::Planet()
{
	name = "Dummy";
	radius = 0.0;
	mass = 0.0;
}

double Planet::SArea()
{
	return 4*M_PI*pow(radius, 2);
}
double Planet::Density()
{
	return 4/3*M_PI*pow(radius, 3);
}
double Planet::g()
{
	return G * mass / pow(radius, 2);
}

bool Planet::SetName(string n)
{
	bool rv = false;
	if (n.length()>0)
	{
		name=n;
		rv = true;
	}
	return rv;
}

bool Planet::SetRadius(double r)
{
	bool rv = false;
	if (r>0.0)
	{
		radius=r;
		rv = true;
	}
	return rv;
}

bool Planet::SetMass(double m)
{
	bool rv = false;
	if (m>0.0)
	{
		mass=m;
		rv = true;
	}
	return rv;
}

void Planet::Input()
{
	while(SetName(ReadString("Name?"))==false)
		cerr<<"Planet must have a name\n";
	while(SetRadius(ReadDouble("Radius?"))==false)
		cerr<<"Value must greater than zero\n";
	while(SetMass(ReadDouble("Mass?"))==false)
		cerr<<"Value must greater than zero\n";
}

void Planet::Display()
{
//	cout << "Place in list: " << i << endl;
	cout << "Planet: " << name << endl;
	cout << "Radius: " << radius << endl;
	cout << "Mass: " << mass << endl;
	cout << "Surface Area: " << SArea() << endl;
	cout << "Density: " << Density() << endl;
	cout << "Gravitational Acceleration: " << g() << endl;
}

void AddPlanet(vector<Planet>& l)
{
	Planet newp;
	newp.Input();
	AddToList(l, newp);
}

void DelPlanet(vector<Planet>& l)
{
	int killp;
	killp = ReadInt("What place in list do you want to delete? ");
	Remove(l, killp);
}

void ListAll(vector<Planet>& l)
{
	if(l.empty()==0)
	{
		for(int i=0; i <=l.size()-1; i++)
		{
			l[i].Display();
		}
	}
	else
	{
		cout << "The list is empty." << endl;
	}
}



void AddToList(vector<Planet>& l, Planet newp)
{
	l.push_back(newp);
	int idx=0;
	BinSearch(l,newp.name,idx);
	for(int i=l.size()-1; i>idx; i--)
	{
		l[i]=l[i-1];
	}
	l[idx]=newp;
}

void Remove(vector<Planet>& list, int idx)
{
	for(int i=idx; i < list.size()-1; i++)
	{
		list[i]=list[i+1];
	}
	list.pop_back();
}

bool BinSearch(vector<Planet>& l, string n, int& index)
{
	bool found=false;
	index=0;
	if (l.empty()==0)
	{
		int curIndex=0;
		int left=0;
		int right=l.size()-1;
		bool done=false;
		while(done==false)
		{
			curIndex=(left+right)/2;
			if(l[curIndex].name==n)
			{
				done=true;
				found=true;
			}
			else
			{ 
				if(l[curIndex].name>n)
				{
					right=curIndex-1;
				}

				else if(l[curIndex].name<n)
				{
					left=curIndex+1;
				}
			}
			if (left>right)
			{
				done=true;
			}
			index=curIndex;
		}
	}
	return found;
}

1
2
3
4
5
6
7
8
#include <string>

using namespace std;

double ReadDouble(string prompt);
int ReadInt(string prompt);
string ReadString(string prompt);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <string>
#include "input.h"
using namespace std;

int ReadInt(string prompt)
{
	int rv = 0;
	cout<< prompt << endl;
	bool done = false;
	while(done == false)
	{
		cin>> rv;
		if(cin.fail() != 0)
		{
			cerr<< "Cannot read data." << endl;
			cin.clear();
			cin.ignore(256,'\n');
		}
		else
		{
			done = true;
		}
	}
	return rv;
}

double ReadDouble(string prompt)
{
	double rv = 0.0;
	cout<< prompt << endl;
	bool done = false;
	while(done == false)
	{
		cin>> rv;
		if(cin.fail() != 0)
		{
			cerr<<"Cannot read data."<<endl;
			cin.clear();
			cin.ignore(256,'\n');
		}
		else
		{
			done = true;
		}
	}
	return rv;
}

string ReadString(string prompt)
{
	string rv = "";
	cout<< prompt << endl;
	bool done = false;
	while(done == false)
	{
		cin>> rv;
		if(cin.fail() != 0)
		{
			cerr<<"Cannot read data."<<endl;
			cin.clear();
			cin.ignore(256,'\n');
		}
		else
		{
			done = true;
		}
	}
	return rv;
}
I don't have access to a debugger, so it's been painful trying to figure it out. Any thoughts would be appreciated.


Thoughts: Reduce the code to a minimal subset that reproduces the problem. This not only helps you locate the problem, it makes it easier for other people to help you and more likely for responses to occur at all.

BinSearch returns a value. Perhaps you should use it for something.

A binary search requires a sorted array. Do not insert your string before you find the place where it should be inserted. Also, consider using std::lower_bound or std::upper_bound instead of your overly complex home-grown version of a binary search.

You might also consider using a container that keeps itself sorted (such as std::set) so you don't have to manually keep things sorted.
Last edited on
Never mind, I solved it. In BinSearch I needed to add after line 250:
 
curIndex++;
Last edited on
Topic archived. No new replies allowed.