Sorting: MERGESORT
Vogliamo ordinare lista (a1,…,an).
1. Dividi lista in 2 sottoliste aventi (quasi) la stessa
dimensione: (a1,a3,a5,…) e (a2,a4,…), (SPLIT)
2. Ordina le due liste separatamente (MERGESORT)
3. Fondi le due liste ottenute (ordinate) in una
unica lista ordinata (MERGE)
MERGE (di due liste ordinate L1,L2 M)
Algoritmo dipende dalla rappresentazione delle liste
Usiamo LISTE A PUNTATORI:
ogni elemento della lista è una struttura
typedef struct CELL *LIST
struct CELL{
int element
/* elemento della lista*/
LIST next
/* puntatore alla successiva
struttura (elemento)*/
}
(a1,a2,…,an)
a1
a2
…
an
MERGE (di due liste ordinate L1,L2 M)
-Trova il minimo tra il primo elemento di L1 e di L2,
rimuovilo dalla lista di appartenenza ed aggiungilo ad M.
Ripeti
LIST merge (LIST list1, LIST list2)
{ if (list1==NULL) return list2
else if (list2==NULL) return list1
-
}
else
if (list1->element <= list2 -> element)
/* entrambe le liste non vuote ed il primo
elemento di list1 è minore del primo di list2*/
{ list1->next=merge(list1->next, list2);
return list1;
}
else /*entrambe le liste non vuote ed il primo
elemento di list2 è minore del primo di list1*/
{ list2->next=merge(list1, list2->next);
return list2;
}
MERGE (di due liste ordinate L1,L2 M)
-Trova il minimo tra il primo elemento di L1 e di L2,
rimuovilo dalla lista di appartenenza ed aggiungilo ad M.
Ripeti
LIST merge (LIST list1, LIST list2)
{ if (list1==NULL) return list2
else if (list2==NULL) return list1
-
}
else
if (list1->element <= list2->element)
/* entrambe le liste non vuote ed il primo
elemento di list1 è minore del primo di list2*/
{ list1->next=merge(list1->next, list2);
return list1;
}
else /*entrambe le liste non vuote ed il primo
elemento di list2 è minore del primo di list1*/
{ list2->next=merge(list1, list2->next);
return list2;
}
MERGE (di due liste ordinate L1,L2 M)
-Trova il minimo tra il primo elemento di L1 e di L2,
rimuovilo dalla lista di appartenenza ed aggiungilo ad M.
Ripeti
LIST merge (LIST list1, LIST list2)
{ if (list1==NULL) return list2
else if (list2==NULL) return list1
-
}
else /* entrambe le liste non vuote*/
if (list1->element <= list2->element)
/* entrambe le liste non vuote ed il primo
elemento di list1 è minore del primo di list2*/
{ list1->next=merge(list1->next, list2);
return list1;
}
else /*entrambe le liste non vuote ed il primo
elemento di list2 è minore del primo di list1*/
{ list2->next=merge(list1, list2->next);
return list2;
}
MERGE (di due liste ordinate L1,L2 M)
LIST merge (LIST list1, LIST list2) {
if (list1==NULL) return list2
else if (list2==NULL) return list1
else if ( list1->element <= list2->element )
{/* entrambe le liste non vuote ed il primo elemento
di list1 è minore del primo di list2*/
list1->next=merge(list1->next, list2);
return list1;}
else
…}
list1
a1
a2
list2
b1
b2
list1
a1
merge
an
…
…
a2
b1
bn
…
…
an
bn
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
list1=merge(list1, list2) merge (2-4-7, 3-5-6-9)
9 p
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
9 p
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
merge(4-7, 5-6-9)
9 p
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
g= merge(g, b)
merge(4-7, 5-6-9)
merge(7, 5-6-9)
9 p
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
merge(4-7, 5-6-9)
g= merge(g, b)
merge(7, 5-6-9)
d= merge(g, d)
merge(7, 6-9)
9 p
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
merge(4-7, 5-6-9)
g= merge(g, b)
merge(7, 5-6-9)
d= merge(g, d)
merge(7, 6-9)
e= merge(g, e)
merge(7, 9)
9 p
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
9 p
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
merge(4-7, 5-6-9)
g= merge(g, b)
merge(7, 5-6-9)
d= merge(g, d)
merge(7, 6-9)
e= merge(g, e)
t= merge(NULL, e)=e
merge(7, 9)
merge( , 9)
e
9
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
9 p
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
merge(4-7, 5-6-9)
g= merge(g, b)
merge(7, 5-6-9)
d= merge(g, d)
merge(7, 6-9)
e= merge(g, e) =g
merge(7, 9)
g
7
t
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
9 p
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
g= merge(g, b)
d= merge(g, d)=d
merge(4-7, 5-6-9)
merge(7, 5-6-9)
merge(7, 6-9)
d
6
e
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
9 p
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b)
g= merge(g, b) = b
merge(4-7, 5-6-9)
merge(7, 5-6-9)
b
5
d
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
9 p
Merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2) merge(4-7,3-5-6-9)
b= merge(a, b) = a
merge(4-7, 5-6-9)
a
4
g
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
9 p
list1=merge(list1, list2) merge (2-4-7, 3-5-6-9)
a= merge(a, list2)=list2 merge(4-7,3-5-6-9) list2
3
b
MERGE (di due liste ordinate L1,L2 M)
list1
2
list2
3 b
a
4
5
g
7 t
d
6 e
list1=merge(list1, list2) merge (2-4-7, 3-5-6-9) list1
9 p
2
a
SPLIT (di L in due liste ordinate L1,L2)
L=(a1,a2, a3, a4, …, an) L1 =(a1, a3, …) , L2 =(a2, a4, …)
LIST Split (LIST list)
{
List pSecondcell;
if (list==NULL) return NULL
else if (list->Next==NULL) return NULL
else
{/* list contiene almeno 2 elementi*/
pScondcell=list->next;
list->next = pSecondcell->next;
pSecondcell->next=split(pSecondcell->next);
return pSecondcell;
}
}
SPLIT (di L in due liste ordinate L1,L2)
LIST Split (LIST list)
{ List pSecondcell;
if (list==NULL) return NULL
else if (list->Next==NULL) return NULL
else {/* list contiene almeno 2 elementi*/
pScondcell=list->next;
list->next = pSecondcell->next;
pSecondcell->next=split(pSecondcell->next);
return pSecondcell;}}
list
a1
a2
a3
…
an
SPLIT (di L in due liste ordinate L1,L2)
LIST Split (LIST list)
{ List pSecondcell;
if (list==NULL) return NULL
else if (list->Next==NULL) return NULL
else {/* list contiene almeno 2 elementi*/
pScondcell=list->next;
list->next = pSecondcell->next;
pSecondcell->next=split(pSecondcell->next);
return pSecondcell;}}
list
pSecondcell
a1
a2
a3
…
an
SPLIT (di L in due liste ordinate L1,L2)
LIST Split (LIST list)
{ List pSecondcell;
if (list==NULL) return NULL
else if (list->Next==NULL) return NULL
else {/* list contiene almeno 2 elementi*/
pScondcell=list->next;
list->next = pSecondcell->next;
pSecondcell->next=split(pSecondcell->next);
return pSecondcell;}}
list
pSecondcell
a1
a2
a3
…
an
SPLIT (di L in due liste ordinate L1,L2)
LIST Split (LIST list)
{ List pSecondcell;
if (list==NULL) return NULL
else if (list->Next==NULL) return NULL
else {/* list contiene almeno 2 elementi*/
pScondcell=list->next;
list->next = pSecondcell->next;
pSecondcell->next=split(pSecondcell->next);
return pSecondcell;}}
list
a1
a2
a3
Split di
pSecondcell
…
an
MERGESORT
BASE: Se la lista contiene 0 o 1 elemento, stop
Ind.: Split di (a1,a2,…) in (a1,a3,…) e (a2,a4,…)
Mergesort delle due liste separatamente
Merge delle 2 liste ordinate
MERGESORT
BASE: Se la lista contiene 0 o 1 elemento, stop
Ind.: Split di (a1,a2,…) in (a1,a3,…) e (a2,a4,…)
Mergesort delle due liste separatamente
Merge delle 2 liste ordinate
LIST Mergesort (LIST list)
{
List SecondList;
if (list==NULL) return NULL
else if (list->next==NULL) return list
else
{/* list contiene almeno 2 elementi (da ordinare)*/
SecondList=split(list);
return merge(mergesort(list),mergesort(ScondList));
}
}
R.T. della funzione SPLIT
LIST Split (LIST list)
{ List pSecondcell;
if (list==NULL) return NULL
else if (list->Next==NULL) return NULL
else {/* list contiene almeno 2 elementi*/
pScondcell=list->next;
list->next = pSecondcell->next;
pSecondcell->next=split(pSecondcell->next);
return pSecondcell;}}
Sia n=|list|. Si ha la relazione di ricorrenza
T(0)=T(1)=O(1)
T(n)=c+T(n-2), per n>1
Quindi T(n)=O(n)
R.T. del MERGE
LIST merge (LIST list1, LIST list2)
{ if (list1==NULL) return list2
else if (list2==NULL) return list1
}
else
if (list1->element <= list2 -> element)
{ list1->next=merge(list1->next, list2);
return list1; }
else
{ list2->next=merge(list1, list2->next);
return list2;}
Siano n1=|list1|, n2=|list2|, n=n1+n2.
Si ha la relazione di ricorrenza
T(0)=T(1)=O(1) (almeno 1 lista vuota)
T(n)=c+T(n-1), per n>1
Quindi T(n)=O(n)
R.T. MERGESORT
LIST Mergesort (LIST list)
{List SecondList;
if (list==NULL) return NULL
else if (list->next==NULL) return list
else /* list contiene almeno 2 elementi (da ordinare)*/
{SecondList=split(list);
return merge(mergesort(list),mergesort(ScondList));}
}
Sia n=|list|. Si ha la relazione di ricorrenza
T(0)=T(1)=O(1) (list contiene 0 o 1 elemento)
T(n)=O(n) + O(n) +T(n/2) +T(n/2)
=O(n) + 2 T(n/2), per n>1
Quindi T(n)=O(n log n)
R.T. MERGESORT
T(0)=T(1)=O(1)
T(n)=c n + 2 T(n/2), per n>1
Si assuma per semplicità che n=2m (cioè m=log n)
T(2m)=c 2m + 2 T(2m-1)
=c 2m + 2 (c 2m-1 + 2 T(2m-2))= c 2m + c 2m +4 T(2m-2)
= 2c 2m + 4 T(2m-2)
= 2c 2m +4 (c 2m-2 + 2 T(2m-3))=2c 2m + c 2m+8T(2m-3)
= 3c 2m + 8 T(2m-3)
……
= i c 2m + 2i T(2m-i)
Scegliendo i=m=log n si ha
T(n)= T(2m) = m c 2m + 2m T(20)= m c n + n a=
= c n log n + a n = O(n log n)
Correttezza MERGESORT
LIST Mergesort (LIST list)
{List SecondList;
if (list==NULL) return NULL
else if (list->next==NULL) return list
else /* list contiene almeno 2 elementi (da ordinare)*/
{SecondList=split(list);
return merge(mergesort(list),mergesort(ScondList));}
}
Assumiamo correttezza delle funz.split e merge (esercizio)
Per induzione completa su n=|list|.
Base. Se n=0 o n=1, restituisce lista inalterata, ok.
Passo (n>1). Assumiamo per i.i. mergesort(list),
mergesort(ScondList) restituiscono liste input ordinate.
Quindi Split divide gli elementi lista input con n elementi tra
list e Secondlist; mergesort(list),mergesort(ScondList)
ordina le liste;
Merge fonde le liste restituendo in output una lista ordinata
contenete gli stessi n elementi della lista input.