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.
Scarica

a merge(4-7, 5-6-9)