Searching
and Sorting
Searching
Boolean search: does the element belong to the set
("yes-no") vs. place search if "place" is defined (index).
Linear search.
Binary search (bisection of
interval).
Hashtable: hash function
(hashcode), collision, collision handling schemes, separate
chaining, open addressing, linear probing, double hashing.
Running time of different
operations for different methods.
Sorting
Abstract properties - time
complexity and space complexity, average and worst case, running
time in practice, ease of programming.
Stable and unstable
methods.
"Slow" methods - quadratic:
insertion sort
"Quick" general methods -
nlogn: quicksort (unstable), merge sort (extra memory), binary
insertion sort (homework!), heapsort (discussed later). Divide
and conquer strategies.
Special methods: counting
sort, radix sort, bucket sort.
Otsimine ja järjestamine
Otsimise ülesanne
Tuvastada etteantud elemendi
kuuluvus etteantud struktuuri.
Tulemuseks võib sõltuvalt ülesandest olla:
tõeväärtus (kuulub-ei kuulu), "asukoht"
struktuuris (või signaal mittekuulumise kohta), element
ise vms.
Meie näidetes üritame leida elemendi asukohta.
Kahendotsimine (Binary Search)
"Lõigu poolitamine"
matemaatikas. On rakendatav kahel eeltingimusel:
- vaadeldav struktuur on järjestatud
- elemendid on indekseeritavad
O(log n)
/**
* Leida etteantud listist etteantud element kahendotsimise abil.
* @param a list.
* @param e otsitav element.
* @returns otsitava elemendi indeks või -1, kui elementi ei leidu.
*/
static public int otsi (List a, Comparable e) {
int j = -1;
int l = 0; // vasakpoolne otspunkt
int r = a.size() - 1; // parempoolne otspunkt
while (l <= r) {
j = (l + r) / 2;
if (e.compareTo ((Comparable)a.get (j)) == 0)
return j;
if (e.compareTo ((Comparable)a.get (j)) > 0)
l = j+1; // vasak otspunkt nihkub paremale
else
r = j-1; // parem otspunkt nihkub vasakule
};
return -1;
} // otsi lopp
Paisktabel
Lugeda vastav peatükk
õpikust!
Võtmed, võtmeruum, paisktabel, paiskfunktsioon,
kollisioonid, välisahelad, lahtine adresseerimine,
topeltpaiskamine
Lisamine ja otsimine: O(1)
Järjestamismeetodid
Abstraktne keerukus,
konkreetne keerukus (keskmine, halvim), mäluvajadus,
algoritmi lihtsus, stabiilsus, ...
"Aeglased" meetodid: O(n2)
- lihtne pistemeetod
- mullimeetod
- valikumeetod
- ...
"Kiired" meetodid: O(nlogn)
Erimeetodid (kitsendustega): O(n)
Positsioonimeetodi
programm
Vaata ka www.sorting-algorithms.com
Pistemeetod (Insertion Sort):
Jada jagatakse
"järjestatud osaks" (algselt tühi) ja
"järjestamata osaks" (algselt kogu jada).
Järjestatud osa pikkust suurendatakse järjekordse
elemendi paigutamisega õigele kohale järjestatud
osas.
/**
* Sorteerida pistemeetodil List, mille elemendid realiseerivad
* liidest Comparable.
* @param a sorteeritav list.
*/
static public void pisteSort (List a) {
if (a.size() < 2) return;
for (int i=1; i<a.size(); i++) {
Comparable b = (Comparable) a.remove (i);
int j;
for (j=0; j<i; j++) {
if (b.compareTo ((Comparable)a.get (j)) < 0) break;
}
a.add (j, b); // pistame b kohale j
}
} // pisteSort() lopp
/**
* Sorteerime massiivi, mille elemendid realiseerivad
* liidest Comparable.
* @param a sorteeritav massiiv.
*/
static public void pisteSort (Comparable[] a) {
if (a.length < 2) return;
for (int i=1; i<a.length; i++) {
Comparable b = a[i];
int j;
for (j=i-1; j>=0; j--) {
if (a[j].compareTo (b) <= 0) break;
a[j+1] = a[j]; // vabastame pistekoha
}
a[j+1] = b; // pistame b kohale
}
} // pisteSort() lopp
Kahendpistemeetod:
"Õige" koht leitakse
kahendotsimisega: O(nlogn), kui "pistmine" oleks O(1)
Ühildusmeetod (Merge Sort):
"Jaga ja valitse" : jagatakse
kogu aeg pooleks (kuni pikkus < 2), pooled ühendatakse
lineaarse keerukusega ühildamise abil, kasutatakse
lisamälu mahuga O(n)
static public <T extends Object
& Comparable<? super T>> void
mergesort
(List<T> massiiv, int l, int r) {
if
(massiiv.size()
< 2) return;
if
((r-l)<2)
return;
int
k
= (l+r)/2;
mergesort
(massiiv,
l, k);
mergesort
(massiiv,
k, r);
merge
(massiiv,
l, k, r);
} //
mergesort() lopp
static public
<T extends Object & Comparable<? super T>>
void
merge
(List<T> massiiv, int l, int k, int r) {
if
(massiiv.size()
< 2) return;
if
((r-l)
< 2) return;
if
(k<=l)
return;
if
(k>=r)
return;
List<T>
abi
= new ArrayList<T>(r-l);
int
n1
= l;
int
n2
= k;
T
elem
= null;
while
(true)
{
if
((n1
< k) && (n2 < r)) {
if
(massiiv.get
(n1).compareTo (massiiv.get (n2)) > 0) {
elem
=
massiiv.get (n2);
n2++;
}
else
{
elem
=
massiiv.get (n1);
n1++;
}
abi.add (elem);
}
else
{
if
(n1
>= k) {
for
(int
i = n2; i < r; i++) {
abi.add
(massiiv.get
(i));
}
break;
}
else
{
for
(int
i = n1; i < k; i++) {
abi.add
(massiiv.get
(i));
}
break;
}
}
}
for
(int
i=l; i < r; i++) {
massiiv.set
(i,
abi.get (i-l));
}
}
Kiirmeetod (Quicksort):
(Osa)jada jagatakse kaheks
lühemaks osajadaks nii, et ükski element esimeses osas
ei oleks suurem ühestki elemendist teises osas. Siis
võib kummagi osa sorteerida eraldi (nad on
sõltumatud). "Jaga ja valitse"
/**
* Sorteerida massiiv kiirmeetodil.
* @param massiiv sorteeritav massiiv.
* @param l vasakpoolne otspunkt.
* @param r parempoolne otspunkt.
*/
static public void sort (Comparable[] massiiv, int l, int r) {
if (massiiv.length < 2) return;
int i = l; int j = r;
Comparable x = massiiv [(i+j) / 2];
do {
while (massiiv [i].compareTo (x) < 0) i++;
while (x.compareTo (massiiv [j]) < 0) j--;
if (i <= j) {
Comparable tmp = massiiv [i];
massiiv [i] = massiiv [j]; massiiv [j] = tmp;
// selle koha peal on väljatrükk silumiseks: "veelahe" ja vahetatavad
i++; j--;
}
} while (i < j);
if (l < j) sort (massiiv, l, j+1); // rekursioon
if (i < r-1) sort (massiiv, i, r); // rekursioon
} // sort() lopp
Otsimisel ja järjestamisel
on abiks
java.util.Arrays, java.util.Collections
J. Pöial