Algoritmy usporadúvania

Quick sort

Implementácia

Ako bolo spomenuté v popise, pri nerekurzívnej podobe algoritmu je potrebné indexy ľavý a pravý ukladať do zásobníka. Najskôr je teda potrebné implementovať zásobník. Nasleduje štruktúra prvku ukladaného v zásobníku, tj. prvok sa skladá z indexu ľavý a pravý. Samotný zásobník je reprezentovaný ako vektor, čo je vlastne zreťazený zoznam (C++). Pre zásobník stačí zadefinovať tri funkcie, ktorých implementácia a popis je nižšie.

typedef struct stack{
	int lavy;
	int pravy;
}stack;

vector zasobnik;

//******************************************************************
//testuje ci je zasobnik prazdny
bool CStack::S_isempty(void)
{
	if(zasobnik.empty())
		return true;
	else return false;
}
//*********************************************************************

//********************************************************************
//vklada hodnotu do zasobnika
void CStack::S_push(int lavy, int pravy)
{
	stack zas;
	zas.lavy = lavy;
	zas.pravy = pravy;

	zasobnik.push_back(zas);
}
//********************************************************************

//*********************************************************************
//vybera hodnotu zo zasobnika, vrchol posuva nizsie
stack* CStack::S_pop()
{
	if(S_isempty()) //tzn zas je prazdny
				return NULL; //neuspech
	
	//stack zas = zasobnik.RemoveTail();
	stack zas;
	zas = zasobnik[zasobnik.size()-1];
	zasobnik.erase(&zasobnik.back());
	return &zas;
}
//********************************************************************
 
Nasleduje funkcia v jazyku C, ktorá implementuje algoritmus Quick sort v jeho nerekurzívnej podobe. Uvedená funkcia vstupné pole celých čísel usporiada vzostupne.
Algoritmus pracuje rovnako ako rekurzívna podoba algoritmu, rozdiel je samozrejme v používaní zásobníka. Rekurzívne volanie je nahradené cyklom, ktorý sa vykonáva pokiaľ sú v zásobníku nejaké hodnoty. Nasledujúca funkcia je okomentovaná len na miestach, kde je rozdiel oproti predchádzajúcej implementácii.

//prve volanie funkcie
int_q_sort_vzostup_nerekurziv(pole_int, 0, dlzka-1);

//******QUICK SORT*******
//vstup: pole celych cisel urcene na usporiadanie, lavy a pravy index, medzi ktorymi bude pole usporiadane (pri prvom volani: lavy = 0 a pravy = dlzka-1)
//ucel: vzostupne usporiadanie zadaneho pola
//algoritmus: Quick sort, nerekurzivna podoba algoritmu
//vystup: (void)
void int_q_sort_vzostup_nerekurziv(int *pole, int lavy, int pravy)
{
	int pivot_index, zac_lavy, zac_pravy;
	int pivot;
	stack *vrchol;
	CStack *zas;
	//vytvorenie noveho zasobnika
	zas = new CStack();
	//vlozenie prvych vstupnych hodnot lavy a pravy do zasobnika
	zas->S_push(lavy, pravy);

	//cyklus bude bezat, pokial v zasobniku nieco bude
	while(!(zas->S_isempty())){
		//vyberieme hodnoty z vrchu zasobnika
		vrchol = zas->S_pop();
		//ulozime si ich do premennych lavy a pravy
		lavy = vrchol->lavy;
		pravy = vrchol->pravy;
		zac_lavy = lavy;
		zac_pravy = pravy;

		presuny++;
		pivot = pole[lavy];
  
		while (lavy < pravy){
			while( (pole[pravy] >= pivot) && (lavy < pravy) ){
				porovnania++;
				pravy--;
			}
			if(lavy < pravy) 
				porovnania++;

			if (lavy != pravy){
				presuny++;
				pole[lavy] = pole[pravy];
				lavy++;			
			}

			while( (pole[lavy] <= pivot) && (lavy < pravy) ){
				porovnania++;
				lavy++;
			}
			if(lavy < pravy)
				porovnania++;

			if (lavy != pravy){
				presuny++;
				pole[pravy] = pole[lavy];
				pravy--;
			}
		}
		
		presuny++;
		pole[lavy] = pivot;
		pivot_index = lavy;

		lavy = zac_lavy;
		pravy = zac_pravy;

		//namiesto volania funkcie nasleduje vlozenie hodnot do zasobnika 
		if (lavy < pivot_index){	
			zas->S_push(lavy, pivot_index-1);
		}
		if (pravy > pivot_index){  
			zas->S_push(pivot_index+1, pravy);
		}
	}
	return;

}