Biggest Rectangle Algorithmus für zweidimensionales Array - Problem

Hikaruchan

Grünschnabel
Hi erstmal!

Ich versuche gerade in einer kleinen testimplementierung diesen Algorithmus http://drdobbs.com/database/184410529?pgno=1 http://drdobbs.com/database/184410529?pgno=1 aus Listing Four zu implementieren. Prinzipiell versteh ich den Algorithmus, allerdings kommt es in meiner Implementierung immer zu einer Assertion mit der Expression: vector iterator + offset out of range.

Meiner Meinung dürfte der Fehler nicht auftreten, aber sowie es scheint, übersehe ich etwas. Nur für den Fall das es wichtig sein sollte, ich mache das ganz mit Visual Studio 2010, es handelt sich um eine C++ Console Application.

Nachfolgend poste ich mal meinen Code, ich glaub die Variablennamen sprechen für sich, falls nicht dann nachfragen *g*, beziehungsweise sind großteils gleich dem beschriebenen Algorithmus des obigen Links.

Ich hoffe es sieht jemand vl. den Fehler, ich sehs nicht, vermutlich is es eh was ganz blödes einfaches. *g*

Code:
#include <iostream>
#include <ctime>
#include <vector>

using namespace std;

int mapsize = 10;

void init(char** map){

	srand(time(0));



	for(int i = 0; i<mapsize; ++i){
		cout<<"\n";
		for(int j = 0; j<mapsize; ++j){
			map[i][j] = (int)(rand()/(double)(RAND_MAX)+0.8)+'0';
		}
	}

	for(int i = 0; i<mapsize; ++i){
		cout<<"\n";
		for(int j = 0; j<mapsize; ++j){
			cout<<map[i][j];
		}
	}
	cout<<"\n\n";

}

struct Pos{
	int x;
	int y;

	Pos(){
		x = 0;
		y = 0;
	}

	Pos(int x, int y){
		this->x = x;
		this->y = y;
	}
};

struct Rectangle{

	Pos ur;
	Pos ll;

	Rectangle(){
		ur = Pos(-1,-1);
		ll = Pos(0,0);
	}

	Rectangle(Pos ur, Pos ll){
		this->ur = ur;
		this->ll = ll;
	}

};

struct TempRect{

	int startPos;
	int width;

	TempRect(int startPos, int width){
		this->startPos = startPos;
		this->width = width;
	}

};

int area(Rectangle best_rect){


	if (best_rect.ll.x > best_rect.ur.x || best_rect.ll.y > best_rect.ur.y){ // If ur is left of or 
		return 0;               // below 11: return 0 
	}
	else{
		return (best_rect.ur.x-best_rect.ll.x+1)*(best_rect.ur.y-best_rect.ll.y+1);
	}

}

void update_cache(int x, char** map, int* cache){

	for(int y = 0; y < mapsize; y++){
		if(map[x][y] != '0'){
			cache[y] = cache[y]+1;
		}else{
			cache[y] = 0;
		}
	}

}

void findBiggestRectangle(char** map){

	int* cache = new int[mapsize];
	vector<TempRect> rectangle_stack;
	Rectangle best_rect;
	TempRect oldRect(0,0);

	for(int i = 0; i < mapsize; i++){
		cache[i] = 0;
	}

	int width = 0;

	for(int x = mapsize-1; x >= 0; x--){
		update_cache(x, map, cache);
		width = 0;
		for(int y = 0; y < mapsize; ++y){
			if(cache[y] > width){
				rectangle_stack.push_back(TempRect(y, width));
				width = cache[y];
			} else if(cache[y] < width){
				do{
					cout<<rectangle_stack.size();
					oldRect = TempRect(rectangle_stack.back().startPos, rectangle_stack.back().width);
					//oldRect = rectangle_stack.back();

					
					rectangle_stack.pop_back();

					if(width*(y-oldRect.startPos) > area(best_rect)){
						best_rect.ll = Pos(x, oldRect.startPos);
						best_rect.ur = Pos(x + width-1, y-1);
					}
					width = oldRect.width;

				}while(cache[y] >= width && rectangle_stack.size() != 0);
				width = cache[y];

				if(width !=0){
					rectangle_stack.push_back(TempRect(oldRect.startPos, width));
				}
			}
		}
	}

	cout<<"ll x: "<<best_rect.ll.x<<" ll y: "<<best_rect.ll.y<<endl;
	cout<<"ur x: "<<best_rect.ur.x<<" ur y: "<<best_rect.ur.y<<endl;
	for(int j = best_rect.ll.y; j <= best_rect.ur.y; ++j){
	for(int i = best_rect.ll.x; i <= best_rect.ur.x; ++i){
		
			map[i][j] = 'x';
		}
	}

	for(int i = 0; i<mapsize; ++i){
		cout<<"\n";
		for(int j = 0; j<mapsize; ++j){
			cout<<map[i][j];
		}
	}
	cout<<"\n\n";

}


int main(void){



	char** map = new char*[mapsize];

	for(int i = 0; i < mapsize; ++i) {
		map[i] = new char[mapsize];
	}

	for(int i = 0; i<mapsize; ++i){
		//cout<<"\n";
		for(int j = 0; j<mapsize; ++j){
			map[i][j] = '0';
			//cout<<map[i][j];
		}
	}
	//cout<<"\n\n";

	init(map);

	findBiggestRectangle(map);


	return 0;
}
 
Zuletzt bearbeitet:
Hi und Willkommen bei tutorials.de :)

Hast du einmal überprüft, in welcher Zeile der Fehler auftritt?

Was übrigens sofort auffällt: Du gibst den mit new reservierten Speicher nicht mehr frei.
Ist nicht der Fehlergrund, aber auch schlecht.
 
Zuletzt bearbeitet:
Erstmal schon danke für die schnelle antwort, seit echt flott hier *g*

Der Fehler tritt in Zeile 123 hier oldRect = TempRect(rectangle_stack.back().startPos, rectangle_stack.back().width); auf.

Also quasi wenn der rectangle_stack die size = 0 hat. Aber wenn das so is, sollt er ja garnicht mehr in dem Code bereich sein.

Das mit dem Speicher ist mir bewusst, wie gesagt, is nur ne schnelle testimplementierung, weils eigentlich für die Anwendung in nem umfangreicheren Projekt gedacht is, drum is der code etwas dirty momentan. *g*
 
Hmm, also bei läuft besagte Zeile fehlerfrei, dafür geht bei 153 was daneben...
schau mir das mal genauer an.
 
ich hab jetzt oben mal den code angepasst, irgendwie passts noch immer nicht, zumindest semmelts jetzt nicht mehr ab. aber das ergebnis scheint nicht zu stimmen, irgendwie, vl. sieht wer warum.
 
Zuletzt bearbeitet:
Zumindest den Absturzgrund kann ich dir jetzt auch sagen :D
Ein i statt einem j in einer Schleifenbedingung...jetzt von dir schon (bewusst?) ausgebessert.
Die Reihenfolge der Schleifen hätte aber auch so bleiben können.

edit: Aber irgendwo ist da noch ein gewaltiges Pointerproblem.
Jetzt bleibt das Programm nämlich an den verschiedensten Stellen einfach stehen, immer wo anders.
Liegt wohl an den Zufallszahlen :D
 
Zuletzt bearbeitet:
jo oben bewusst ausgebessert, hätt ich vl. erwähnen sollen ^^

jo das ergebnis stimmt aber igendwie leider nicht, egal ob ich die reihenfolge der schleifen umdrehe oder lasse, puh diese algo kostet mich mehr nerven als ich dache. *g*

@Sheel: aha, machts bei mir nicht, also es scheint immer auf ein ergebnis zu kommen, aber halt nit das richtige bei mir zumindest. aber durchlaufen tuts schon.
 
Zuletzt bearbeitet:
Einmal ganz unabhängig von Pointer- und Compilerwitzen:
Wtf ist die Funktion area?
Warum für x und y plus 1?
4x2 ist für mich 8. area sagt 15.
 
das +1 is, damit die Fläche bei einzelnem Kasterl ned null, sonderrn 1 is
bzw. einzelne Zeilen und Spalten wärn ja sonst auch imemr Fläche null

bei kommt da übrigens schon stimmiges an werten raus
 
Zurück