Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
1 result

Target

Select target project
No results found
Select Git revision
  • master
1 result
Show changes

Commits on Source 525

425 additional commits have been omitted to prevent performance issues.
1000 files
+ 189998
620
Compare changes
  • Side-by-side
  • Inline

Files

+5 −0
Original line number Diff line number Diff line
*.o
*.xopp*
slides/package-lock.json
slides/package.json
slides/.vscode/settings.json
.vscode/settings.json
slides/node_modules/.package-lock.json

README.md

0 → 100644
+17 −0
Original line number Diff line number Diff line
# Remerciements et contributions

Merci aux contributeurs suivants pour leurs efforts (dans un ordre alphabétique):

* P. Albuquerque
* J. Bach
* A. Boyer
* M. Corboz
* M. Divià
* Y. El Hakouni
* A. Escribano
* P. Kunzli
* G. Legouic
* G. Marino Jarrin
* H. Radhwan
* I. Saroukhanian
* C. Volta
+470 −0
Original line number Diff line number Diff line
@charset "UTF-8";

/* Import ET Book styles
   adapted from https://github.com/edwardtufte/et-book/blob/gh-pages/et-book.css */

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot");
    src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.woff") format("woff"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.ttf") format("truetype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot");
    src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.woff") format("woff"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.ttf") format("truetype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot");
    src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.woff") format("woff"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.ttf") format("truetype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.svg#etbookromanosf") format("svg");
    font-weight: bold;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "et-book-roman-old-style";
    src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot");
    src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.woff") format("woff"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.ttf") format("truetype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

/* Tufte CSS styles */
html {
    font-size: 15px;
}

body {
    width: 87.5%;
    margin-left: auto;
    margin-right: auto;
    padding-left: 12.5%;
    font-family: et-book, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
    background-color: #fffff8;
    color: #111;
    max-width: 1400px;
    counter-reset: sidenote-counter;
}

h1 {
    font-weight: 400;
    margin-top: 4rem;
    margin-bottom: 1.5rem;
    font-size: 3.2rem;
    line-height: 1;
}

h2 {
    font-style: italic;
    font-weight: 400;
    margin-top: 2.1rem;
    margin-bottom: 1.4rem;
    font-size: 2.2rem;
    line-height: 1;
}

h3 {
    font-style: italic;
    font-weight: 400;
    font-size: 1.7rem;
    margin-top: 2rem;
    margin-bottom: 1.4rem;
    line-height: 1;
}

hr {
    display: block;
    height: 1px;
    width: 55%;
    border: 0;
    border-top: 1px solid #ccc;
    margin: 1em 0;
    padding: 0;
}

p.subtitle {
    font-style: italic;
    margin-top: 1rem;
    margin-bottom: 1rem;
    font-size: 1.8rem;
    display: block;
    line-height: 1;
}

.numeral {
    font-family: et-book-roman-old-style;
}

.danger {
    color: red;
}

article {
    padding: 5rem 0rem;
}

section {
    padding-top: 1rem;
    padding-bottom: 1rem;
}

p,
dl,
ol,
ul {
    font-size: 1.4rem;
    line-height: 2rem;
}

p {
    margin-top: 1.4rem;
    margin-bottom: 1.4rem;
    padding-right: 0;
    vertical-align: baseline;
}

/* Chapter Epigraphs */
div.epigraph {
    margin: 5em 0;
}

div.epigraph > blockquote {
    margin-top: 3em;
    margin-bottom: 3em;
}

div.epigraph > blockquote,
div.epigraph > blockquote > p {
    font-style: italic;
}

div.epigraph > blockquote > footer {
    font-style: normal;
}

div.epigraph > blockquote > footer > cite {
    font-style: italic;
}
/* end chapter epigraphs styles */

blockquote {
    font-size: 1.4rem;
}

blockquote p {
    width: 55%;
    margin-right: 40px;
}

blockquote footer {
    width: 55%;
    font-size: 1.1rem;
    text-align: right;
}

section > p,
section > footer,
section > table {
    width: 55%;
}

/* 50 + 5 == 55, to be the same width as paragraph */
section > dl,
section > ol,
section > ul {
    width: 50%;
    -webkit-padding-start: 5%;
}

dt:not(:first-child),
li:not(:first-child) {
    margin-top: 0.25rem;
}

figure {
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
    max-width: 55%;
    -webkit-margin-start: 0;
    -webkit-margin-end: 0;
    margin: 0 0 3em 0;
}

figcaption {
    float: right;
    clear: right;
    margin-top: 0;
    margin-bottom: 0;
    font-size: 1.1rem;
    line-height: 1.6;
    vertical-align: baseline;
    position: relative;
    max-width: 40%;
}

figure.fullwidth figcaption {
    margin-right: 24%;
}

/* Links: replicate underline that clears descenders */
a:link,
a:visited {
    color: inherit;
}

.no-tufte-underline:link {
    background: unset;
    text-shadow: unset;
}

a:link, .tufte-underline, .hover-tufte-underline:hover {
    text-decoration: none;
    background: -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(currentColor, currentColor);
    background: linear-gradient(#fffff8, #fffff8), linear-gradient(#fffff8, #fffff8), linear-gradient(currentColor, currentColor);
    -webkit-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    -moz-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    background-repeat: no-repeat, no-repeat, repeat-x;
    text-shadow: 0.03em 0 #fffff8, -0.03em 0 #fffff8, 0 0.03em #fffff8, 0 -0.03em #fffff8, 0.06em 0 #fffff8, -0.06em 0 #fffff8, 0.09em 0 #fffff8, -0.09em 0 #fffff8, 0.12em 0 #fffff8, -0.12em 0 #fffff8, 0.15em 0 #fffff8, -0.15em 0 #fffff8;
    background-position: 0% 93%, 100% 93%, 0% 93%;
}

@media screen and (-webkit-min-device-pixel-ratio: 0) {
    a:link, .tufte-underline, .hover-tufte-underline:hover {
        background-position-y: 87%, 87%, 87%;
    }
}

a:link::selection,
a:link::-moz-selection {
    text-shadow: 0.03em 0 #b4d5fe, -0.03em 0 #b4d5fe, 0 0.03em #b4d5fe, 0 -0.03em #b4d5fe, 0.06em 0 #b4d5fe, -0.06em 0 #b4d5fe, 0.09em 0 #b4d5fe, -0.09em 0 #b4d5fe, 0.12em 0 #b4d5fe, -0.12em 0 #b4d5fe, 0.15em 0 #b4d5fe, -0.15em 0 #b4d5fe;
    background: #b4d5fe;
}

/* Sidenotes, margin notes, figures, captions */
img {
    max-width: 100%;
}

.sidenote,
.marginnote {
    float: right;
    clear: right;
    margin-right: -60%;
    width: 50%;
    margin-top: 0.3rem;
    margin-bottom: 0;
    font-size: 1.1rem;
    line-height: 1.3;
    vertical-align: baseline;
    position: relative;
}

.sidenote-number {
    counter-increment: sidenote-counter;
}

.sidenote-number:after,
.sidenote:before {
    font-family: et-book-roman-old-style;
    position: relative;
    vertical-align: baseline;
}

.sidenote-number:after {
    content: counter(sidenote-counter);
    font-size: 1rem;
    top: -0.5rem;
    left: 0.1rem;
}

.sidenote:before {
    content: counter(sidenote-counter) " ";
    font-size: 1rem;
    top: -0.5rem;
}

blockquote .sidenote,
blockquote .marginnote {
    margin-right: -82%;
    min-width: 59%;
    text-align: left;
}

div.fullwidth,
table.fullwidth {
    width: 100%;
}

div.table-wrapper {
    overflow-x: auto;
    font-family: "Trebuchet MS", "Gill Sans", "Gill Sans MT", sans-serif;
}

.sans {
    font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
    letter-spacing: .03em;
}

code, pre > code {
    font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
    font-size: 1.0rem;
    line-height: 1.42;
    -webkit-text-size-adjust: 100%; /* Prevent adjustments of font size after orientation changes in iOS. See https://github.com/edwardtufte/tufte-css/issues/81#issuecomment-261953409 */
}

.sans > code {
    font-size: 1.2rem;
}

h1 > code,
h2 > code,
h3 > code {
    font-size: 0.80em;
}

.marginnote > code,
.sidenote > code {
    font-size: 1rem;
}

pre > code {
    font-size: 0.9rem;
    width: 52.5%;
    margin-left: 2.5%;
    overflow-x: auto;
    display: block;
}

pre.fullwidth > code {
    width: 90%;
}

.fullwidth {
    max-width: 90%;
    clear:both;
}

span.newthought {
    font-variant: small-caps;
    font-size: 1.2em;
}

input.margin-toggle {
    display: none;
}

label.sidenote-number {
    display: inline;
}

label.margin-toggle:not(.sidenote-number) {
    display: none;
}

.iframe-wrapper {
    position: relative;
    padding-bottom: 56.25%; /* 16:9 */
    padding-top: 25px;
    height: 0;
}

.iframe-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

@media (max-width: 760px) {
    body {
        width: 84%;
        padding-left: 8%;
        padding-right: 8%;
    }

    hr,
    section > p,
    section > footer,
    section > table {
        width: 100%;
    }

    pre > code {
        width: 97%;
    }

    section > dl,
    section > ol,
    section > ul {
        width: 90%;
    }

    figure {
        max-width: 90%;
    }

    figcaption,
    figure.fullwidth figcaption {
        margin-right: 0%;
        max-width: none;
    }

    blockquote {
        margin-left: 1.5em;
        margin-right: 0em;
    }

    blockquote p,
    blockquote footer {
        width: 100%;
    }

    label.margin-toggle:not(.sidenote-number) {
        display: inline;
    }

    .sidenote,
    .marginnote {
        display: none;
    }

    .margin-toggle:checked + .sidenote,
    .margin-toggle:checked + .marginnote {
        display: block;
        float: left;
        left: 1rem;
        clear: both;
        width: 95%;
        margin: 1rem 2.5%;
        vertical-align: baseline;
        position: relative;
    }

    label {
        cursor: pointer;
    }

    div.table-wrapper,
    table {
        width: 85%;
    }

    img {
        width: 100%;
    }
}
Original line number Diff line number Diff line
*.pdf
*.json
*.err
*.markdown
*.html
index.md

slides/.puppeteer.json

deleted100644 → 0
+0 −4
Original line number Diff line number Diff line
{
    "executablePath": "/usr/bin/chromium-browser",
    "args": ["--no-sandbox"]
}
+14 −22
Original line number Diff line number Diff line
@@ -8,46 +8,37 @@ PDFOPTIONS += -V themeoptions:numbering=none -V themeoptions:progressbar=foot
PDFOPTIONS += -V fontsize=smaller
PDFOPTIONS += -V urlcolor=blue

REVEALOPTIONS = -t revealjs
REVEALOPTIONS += -F mermaid-filter
REVEALOPTIONS += --self-contained
REVEALOPTIONS += -V revealjs-url=reveal.js
REVEALOPTIONS += -V theme=white
REVEALOPTIONS += -V width=1920
REVEALOPTIONS += -V margin=0
REVEALOPTIONS += --slide-level=1

MD=$(wildcard *.md) # Tous les fichiers .md
PDF=$(MD:%.md=%.pdf) # Pour les fichier pdf on transforme .md -> .pdf
HTML=$(MD:%.md=%.html) # Pour les fichier html on transforme .md -> .html
MARKDOWN=$(MD:%.md=%.markdown) # Pour les fichier markdown on transforme .md -> .markdown
CHROMIUM:=$(shell which chromium || which chromium-browser)

all: puppeteer $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.pdf
all: puppeteer $(PDF) 
# all: puppeteer $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.pdf

docker: docker-compose.yml
	docker-compose run slides make puppeteer -k || true
	docker-compose run slides make all -k || true
	docker compose run slides

docker_clean: docker-compose.yml
	docker-compose run slides make clean -k || true
	docker compose run slides clean

puppeteer:
	@echo "Setting chromium to $(CHROMIUM) for puppeteer"
	@echo -e "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json
	# @echo "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json

index.md: gen_index.sh
	$(shell ./gen_index.sh)

index:
	rm -f index.md
	./gen_index.sh
index.html: index.md
	pandoc -s $(OPTIONS) --css ../css/tufte-css/tufte.css -o $@ $^

markdown: $(MARKDOWN) # La markdown les cibles %.markdown

%.pdf: %.md metadata.yaml # %.pdf (chaque fichier %.md génère un fichier avec le même nom mais l'extension .pdf et la dépendance metadata.yaml)
	pandoc -s $(OPTIONS) $(PDFOPTIONS) -o $@ $^

%.html: %.md metadata.yaml
	pandoc -s $(OPTIONS) $(REVEALOPTIONS) -o $@ $^

%.markdown: %.md metadata.yaml yq
	sed '1 { /^---/ { :a N; /\n---/! ba; d} }' $< > no_header
	grep -v -F -x -f  no_header $< > header.yaml
@@ -60,11 +51,12 @@ yq: # On peut même télécharger un petit programme avec notre makefile
	wget -nc https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64
	chmod "u+x" yq_linux_amd64 

deploy: all 
deploy: all index.html
	mkdir -p algo_cours
	cp *.pdf algo_cours
	cp index.html algo_cours

clean:
	rm -f *.html *.pdf *.markdown yq_linux_amd64* index.md .puppeteer.json
	rm -rf *.html *.pdf *.markdown yq_linux_amd64* index.md .puppeteer.json algo_cours *.err

.PHONY:	clean index puppeteer yq
.PHONY:	clean index.md puppeteer yq
+19 −363
Original line number Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2021-09-22"
title: "Introduction aux algorithmes I"
date: "2025-09-16"
---

# Qu'est-ce qu'un algorithme?
@@ -42,7 +42,7 @@ de résoudre typiquement une classe de problèmes ou effectuer un calcul.

. . .

* Opérateurs (arthimétiques / booléens)
* Opérateurs (arithmétiques / booléens)
* Boucles;
* Structures de contrôle;
* Fonctions;
@@ -57,14 +57,12 @@ Nombre premier: nombre possédant deux diviseurs entiers distincts.
## Algorithme naïf (problème)

```C
est_premier(nombre) {
    si {
        pour tout i, t.q. 1 < i < nombre {
booléen est_premier(nombre) 
    si 
        pour tout i, t.q. 1 < i < nombre 
            i ne divise pas nombre
        }
    } alors vrai
    alors vrai
    sinon faux
}
```

. . .
@@ -80,14 +78,12 @@ est_premier(nombre) {
## Algorithme naïf (une solution)

```C
est_premier(nombre) { // fonction
    soit i := 2;       // variable, type, assignation
    tant que i < nombre { // boucle
        si nombre modulo i = 0 { // expression typée
booléen est_premier(nombre) // fonction
    soit i = 2       // variable, type, assignation
    tant que i < nombre // boucle
        si nombre modulo i == 0 // expression typée
            retourne faux    // expression typée
        }
        i := i + 1
    }
        i = i + 1
    retourne vrai // expression typée
```

@@ -103,7 +99,7 @@ bool est_premier(int nombre) {
        if (0 == nombre % i) { // is i divise nombre
            return false; // i n'est pas premier
        }
        i += 1; // sinon on incrémente i
        i = i + 1; // sinon on incrémente i
    }
    return true;
}
@@ -125,9 +121,9 @@ bool est_premier(int nombre) {

- Il existe une multitude d'options de compilation:

    ```bash
    $ gcc -O1 -std=c11 -Wall -Wextra -g porg.c -o prog -fsanitize=address 
    -fsanitize=leak -fsanitize=undefined
    ```console
    $ gcc -O1 -std=c11 -Wall -Wextra -g prog.c -o prog 
    	-fsanitize=address 
    ```
    1. `-std=c11` utilisation de C11.
    2. `-Wall et -Wextra` activation des warnings.
@@ -244,7 +240,7 @@ int main() {

# Quiz: compile ou compile pas?

## [Quiz: compile ou compile pas](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033948)
## [Quiz: compile ou compile pas](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501934)

# Types de base (1/4)

@@ -292,7 +288,7 @@ Type Signification

# Quiz: booléens

## [Quiz: booléens](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1032492)
## [Quiz: booléens](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501922)

<!-- TODO Quiz en ligne -->
<!-- ```C
@@ -336,7 +332,7 @@ if (x) { /* vrai */ }

# Quiz: conversions

## [Quiz: conversions](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033446)
## [Quiz: conversions](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501925)

<!-- TODO Quiz en ligne -->
<!-- ```C
@@ -351,343 +347,3 @@ bool d = 2.78; // 1
bool e = 1.0; // 1
``` -->
# Expressions et opérateurs (1/6)

Une expression est tout bout de code qui est **évalué**.

## Expressions simples

- Pas d'opérateurs impliqués.
- Les littéraux, les variables, et les constantes.

```C
const int L = -1; // 'L' est une constante, -1 un littéral
int x = 0;        // '0' est un litéral
int y = x;        // 'x' est une variable
int z = L;        // 'L' est une constante
```

## Expressions complexes

- Obtenues en combinant des *opérandes* avec des *opérateurs*

```C
int x;     // pas une expression (une instruction)
x = 4 + 5; // 4 + 5 est une expression
           // dont le résultat est affecté à 'x'
```

# Expressions et opérateurs (2/6)

## Opérateurs relationnels

Opérateurs testant la relation entre deux *expressions*:

  - `(a opérateur b)` retourne `1`{.C} si l'expression s'évalue à `true`{.C}, `0`{.C} si l'expression s'évalue à `false`{.C}.

| Opérateur | Syntaxe      | Résultat             |
|-----------|--------------|----------------------|
| `<`{.C}   | `a < b`{.C}  | 1 si a <  b; 0 sinon |
| `>`{.C}   | `a > b`{.C}  | 1 si a >  b; 0 sinon |
| `<=`{.C}  | `a <= b`{.C} | 1 si a <= b; 0 sinon |
| `>=`{.C}  | `a >= b`{.C} | 1 si a >= b; 0 sinon |
| `==`{.C}  | `a == b`{.C} | 1 si a == b; 0 sinon |
| `!=`{.C}  | `a != b`{.C} | 1 si a != b; 0 sinon |

# Expressions et opérateurs (3/6)

## Opérateurs logiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `&&`{.C}  | `a && b`{.C} | ET logique           |
| `||`{.C}  | `a || b`{.C} | OU logique           |
| `!`{.C}   | `!a`{.C}     | NON logique          |

# Quiz: opérateurs logiques

## [Quiz: opérateurs logiques](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033629)

<!-- TODO: Quiz -->
<!-- ```C
1 && 0 == 0
7 && 3 == 1
4 || 3 == 1
!34 == 0
!0 == 1

Soit n un unsigned char initialisé à 127:
!n == 0
``` -->

# Expressions et opérateurs (4/6)

## Opérateurs arithmétiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `+`{.C}   | `a + b`{.C}  | Addition             |
| `-`{.C}   | `a - b`{.C}  | Soustraction         |
| `*`{.C}   | `a * b`{.C}  | Multiplication       |
| `/`{.C}   | `a / b`{.C}  | Division             |
| `%`{.C}   | `a % b`{.C}  | Modulo               |

# Expressions et opérateurs (5/6)

## Opérateurs d'assignation

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `=`{.C}   | `a = b`{.C}  | Affecte la valeur `b` à la variable `a`     |
|           |              | et retourne la valeur de `b`                |
| `+=`{.C}  | `a += b`{.C} | Additionne la valeur de `b` à `a` et        |
|           |              | assigne le résultat à `a`.                  |
| `-=`{.C}  | `a -= b`{.C} | Soustrait la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `*=`{.C}  | `a *= b`{.C} | Multiplie la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `/=`{.C}  | `a /= b`{.C} | Divise la valeur de `b` à `a` et            |
|           |              | assigne le résultat à `a`.                  |
| `%=`{.C}  | `a %= b`{.C} | Calcule le modulo la valeur de `b` à `a` et |
|           |              | assigne le résultat à `a`.                  |

# Expressions et opérateurs (6/6)

## Opérateurs d'assignation (suite)

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `++`{.C}  | `++a`{.C}    | Incrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a += 1`).            |
| `--`{.C}  | `--a`{.C}    | Décrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a -= 1`).            |
| `++`{.C}  | `a++`{.C}    | Retourne `a`{.C} et incrémente `a` de 1.    |
| `--`{.C}  | `a--`{.C}    | Retourne `a`{.C} et décrémente `a` de 1.    |


# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (1/2)

## Syntaxe

```C
if (expression) {
    instructions;
} else if (expression) { // optionnel
                         // il peut y en avoir plusieurs
    instructions;
} else {
    instructions; // optionnel
}
```

```C
if (x) { // si x s'évalue à `vrai`
    printf("x s'évalue à vrai.\n");
} else if (y == 8) { // si y vaut 8
    printf("y vaut 8.\n");
} else {
    printf("Ni l'un ni l'autre.\n");
}
```

# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (2/2)

## Pièges

```C
int x, y;
x = y = 3;
if (x = 2)
    printf("x = 2 est vrai.\n");
else if (y < 8)
    printf("y < 8.\n");
else if (y == 3)
    printf("y vaut 3 mais cela ne sera jamais affiché.\n");
else
    printf("Ni l'un ni l'autre.\n");
    x = -1; // toujours évalué
```

# Quiz: `if ... else`{.C}

## [Quiz: `if ... else`{.C}](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033916)


# Structures de contrôle: `while`{.C}

## La boucle `while`{.C}

```C
while (condition) {
    instructions;
}
do {
    instructions;
} while (condition);
```

## La boucle `while`{.C}, un exemple

```C
int sum = 0; // syntaxe C99
while (sum < 10) {
    sum += 1;
}
do {
    sum += 10;
} while (sum < 100)
```

# Structures de contrôle: `for`{.C}

## La boucle `for`{.C}

```C
for (expression1; expression2; expression3) {
    instructions;
}
```

## La boucle `for`{.C}

```C
int sum = 0; // syntaxe C99
for (int i = 0; i < 10; i++) {
    sum += i;
}

for (int i = 0; i != 1; i = rand() % 4) { // ésotérique
    printf("C'est plus ésotérique.\n");
}
```

# Exercice: la factorielle

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un pseudo-code

. . .

```C
int factorielle(int n) {
    i = 1;
    fact = 1;
    pour i <= n {
        fact *= i;
        i += 1;
    }
}
```

# Exercice: la factorielle

\footnotesize

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un code en C

Quand vous avez fini postez le code sur le salon matrix.

. . .

```C
#include <stdio.h>
int main() {
   int nb = 10;
   int fact = 1;
   int iter = 2;
   while (iter <= nb) {
      fact *= iter;
      iter++;
   }
}
```

. . .

## Comment améliorer ce code? (notez ça sur une feuille)


# Entrées/sorties: `printf()`{.C} (1/2)

## Généralités

- La fonction `printf()`{.C} permet d'afficher du texte sur le terminal:

    ```C
    int printf(const char *format, ...);
    ```
- Nombre d'arguments variables.
- `format`{.C} est le texte, ainsi que le format (type) des variables à afficher.
- Les arguments suivants sont les expressions à afficher.

# Entrées/sorties: `printf()`{.C} (2/2)

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Hello world.\n");
    int val = 1;
    printf("Hello world %d time.\n", val);
    printf("%f squared is equal to %f.\n", 2.5, 2.5*2.5);
    return EXIT_SUCCESS;
}
```

# Entrées/sorties: `scanf()`{.C} (1/2)

## Généralités

- La fonction `scanf()`{.C} permet de lire du texte formaté entré au clavier:

    ```C
    int scanf(const char *format, ...);
    ```

- `format`{.C} est le format des variables à lire (comme `printf()`{.C}).
- Les arguments suivants sont les variables où sont stockées les valeurs lues.

# Entrées/sorties: `scanf()`{.C} (2/2)

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Enter 3 numbers: \n");
    int i, j, k;
    scanf("%d %d %d", &i, &j, &k);
    printf("You entered: %d %d %d\n", i, j, k);
    
    return EXIT_SUCCESS;
}
```

# Exercice: la factorielle en mieux

## Individuellement

1. Ajoutez des fonctionnalités à votre code.
2. Écrivez l'algorithme de calcul de deux façon différentes.
3. Pour celles et ceux qui ont fini pendant que les autres essaient: faites-le 
   en récursif (sans aide).

. . .

## Postez vos solutions sur matrix!

+302 −159
Original line number Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2021-09-29"
title: "Introduction aux algorithmes II"
date: "2025-09-23"
---

# Rappel

* Quel est l'algorithme pour le calcul des nombres 1ers?

. . .

```C
bool est_premier(int nombre) {
    int i = 2; // bonne pratique!
    while (i < nombre) { // penser à bien indenter!
        if (0 == nombre % i) { // ça rend le code LISIBLE!
            return false;
        }
        i += 1;
    }
    return true;
}
```

# Expressions et opérateurs (1/6)

Une expression est tout bout de code qui est **évalué**.

## Expressions simples

- Pas d'opérateurs impliqués.
- Les littéraux, les variables, et les constantes.

```C
const int L = -1; // 'L' est une constante, -1 un littéral
int x = 0;        // '0' est un litéral
int y = x;        // 'x' est une variable
int z = L;        // 'L' est une constante
```

## Expressions complexes

- Obtenues en combinant des *opérandes* avec des *opérateurs*

```C
int x;     // pas une expression (une instruction)
x = 4 + 5; // 4 + 5 est une expression
           // dont le résultat est affecté à 'x'
```

# Expressions et opérateurs (2/6)

## Opérateurs relationnels

Opérateurs testant la relation entre deux *expressions*:

  - `(a opérateur b)` retourne `1`{.C} si l'expression s'évalue à `true`{.C}, `0`{.C} si l'expression s'évalue à `false`{.C}.

| Opérateur | Syntaxe      | Résultat             |
|-----------|--------------|----------------------|
| `<`{.C}   | `a < b`{.C}  | 1 si a <  b; 0 sinon |
| `>`{.C}   | `a > b`{.C}  | 1 si a >  b; 0 sinon |
| `<=`{.C}  | `a <= b`{.C} | 1 si a <= b; 0 sinon |
| `>=`{.C}  | `a >= b`{.C} | 1 si a >= b; 0 sinon |
| `==`{.C}  | `a == b`{.C} | 1 si a == b; 0 sinon |
| `!=`{.C}  | `a != b`{.C} | 1 si a != b; 0 sinon |

# Expressions et opérateurs (3/6)

## Opérateurs logiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `&&`{.C}  | `a && b`{.C} | ET logique           |
| `||`{.C}  | `a || b`{.C} | OU logique           |
| `!`{.C}   | `!a`{.C}     | NON logique          |

# Quiz: opérateurs logiques

## [Quiz: opérateurs logiques](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501928)

<!-- TODO: Quiz -->
<!-- ```C
1 && 0 == 0
7 && 3 == 1
4 || 3 == 1
!34 == 0
!0 == 1

Soit n un unsigned char initialisé à 127:
!n == 0
``` -->

# Expressions et opérateurs (4/6)

## Opérateurs arithmétiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `+`{.C}   | `a + b`{.C}  | Addition             |
| `-`{.C}   | `a - b`{.C}  | Soustraction         |
| `*`{.C}   | `a * b`{.C}  | Multiplication       |
| `/`{.C}   | `a / b`{.C}  | Division             |
| `%`{.C}   | `a % b`{.C}  | Modulo               |

# Expressions et opérateurs (5/6)

## Opérateurs d'assignation

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `=`{.C}   | `a = b`{.C}  | Affecte la valeur `b` à la variable `a`     |
|           |              | et retourne la valeur de `b`                |
| `+=`{.C}  | `a += b`{.C} | Additionne la valeur de `b` à `a` et        |
|           |              | assigne le résultat à `a`.                  |
| `-=`{.C}  | `a -= b`{.C} | Soustrait la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `*=`{.C}  | `a *= b`{.C} | Multiplie la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `/=`{.C}  | `a /= b`{.C} | Divise la valeur de `b` à `a` et            |
|           |              | assigne le résultat à `a`.                  |
| `%=`{.C}  | `a %= b`{.C} | Calcule le modulo la valeur de `b` à `a` et |
|           |              | assigne le résultat à `a`.                  |

# Expressions et opérateurs (6/6)

## Opérateurs d'assignation (suite)

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `++`{.C}  | `++a`{.C}    | Incrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a += 1`).            |
| `--`{.C}  | `--a`{.C}    | Décrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a -= 1`).            |
| `++`{.C}  | `a++`{.C}    | Retourne `a`{.C} et incrémente `a` de 1.    |
| `--`{.C}  | `a--`{.C}    | Retourne `a`{.C} et décrémente `a` de 1.    |


# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (1/2)

## Syntaxe

```C
if (expression) {
    instructions;
} else if (expression) { // optionnel
                         // il peut y en avoir plusieurs
    instructions;
} else {
    instructions; // optionnel
}
```

```C
if (x) { // si x s'évalue à `vrai`
    printf("x s'évalue à vrai.\n");
} else if (y == 8) { // si y vaut 8
    printf("y vaut 8.\n");
} else {
    printf("Ni l'un ni l'autre.\n");
}
```

# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (2/2)

## Pièges

```C
int x, y;
x = y = 3;
if (x = 2)
    printf("x = 2 est vrai.\n");
else if (y < 8)
    printf("y < 8.\n");
else if (y == 3)
    printf("y vaut 3 mais cela ne sera jamais affiché.\n");
else
    printf("Ni l'un ni l'autre.\n");
    x = -1; // toujours évalué
```

# Quiz: `if ... else`{.C}

## [Quiz: `if ... else`{.C}](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501931)


# Structures de contrôle: `while`{.C}

## La boucle `while`{.C}

```C
while (condition) {
    instructions;
}
do {
    instructions;
} while (condition);
```

## La boucle `while`{.C}, un exemple

```C
int sum = 0; // syntaxe C99
while (sum < 10) {
    sum += 1;
}
do {
    sum += 10;
} while (sum < 100);
```

# Structures de contrôle: `for`{.C}

## La boucle `for`{.C}

```C
for (expression1; expression2; expression3) {
    instructions;
}
```

## La boucle `for`{.C}

```C
int sum = 0; // syntaxe C99
for (int i = 0; i < 10; i++) {
    sum += i;
}

for (int i = 0; i != 1; i = rand() % 4) { // ésotérique
    printf("C'est plus ésotérique.\n");
}
```


# Exercice: la factorielle

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un pseudo-code

. . .

```python
entier factorielle(entier n)
    i = 1
    fact = 1
    tant que i <= n
        fact *= i
        i += 1
    retourne fact
```

# Exercice: la factorielle

\footnotesize

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un code en C

Quand vous avez fini postez le code sur le salon matrix.

. . .

```C
#include <stdio.h>
int main() {
   int nb = 10;
   int fact = 1;
   int iter = 2;
   while (iter <= nb) {
      fact *= iter;
      iter++;
   }
   printf("La factorielle de %d est %d\n", nb, fact);
}
```

. . .

## Comment améliorer ce code? (notez ça sur une feuille)


# Exercice: la factorielle en mieux

## Individuellement

1. Écrivez l'algorithme de calcul de deux façon différentes.
2. Que se passe-t-il si $n>=15$?
3. Pour celles et ceux qui ont fini pendant que les autres essaient: faites-le 
   en récursif (sans aide).

. . .

## Postez vos solutions sur **matrix**!

# Exercice: test si un nombre est premier

## Avec tout ce que vous avez appris la dernière fois:
## Avec tout ce que vous avez appris jusqu'ici:

* Écrivez le code testant si un nombre est premier.
* Quels sont les ajouts possibles par rapport au code de la semaine passée?
@@ -159,12 +457,6 @@ Par groupe de 3 (5-10min):
Si un nombre, `p`, est multiple de `a` et de `b` alors il peut s'écrire `p = a
* i = b * j`  ou encore `p / a = i` et `p / b = j`.

<!-- Si un nombre, $p$, est multiple de $a$ et de $b$ alors il peut s'écrire -->
<!-- $$ -->
<!-- p = a \cdot i = b \cdot j, -->
<!-- $$ -->
<!-- ou encore $p / a = i$ et $p / b = j$. -->

. . .

## Pseudo-code
@@ -172,7 +464,7 @@ Si un nombre, `p`, est multiple de `a` et de `b` alors il peut s'écrire `p = a
```C
int ppcm(int a, int b) {
    for (i in [1, b]) {
        if a * i is divisible by b {
        if a * i est divisible par b {
            return a * i
        }
    }
@@ -191,7 +483,6 @@ int ppcm(int a, int b) {
```C
#include <stdio.h>
#include <stdlib.h> 

int main() { 
   int n = 15, m = 12;
   int i = 1;
@@ -209,7 +500,6 @@ int main() {
```C
#include <stdio.h>
#include <stdlib.h> 

int main() { 
   int res = n*m;
   for (int i = 2; i <= m; i++) {
@@ -222,153 +512,6 @@ int main() {
}
```

# Le calcul du PGCD (1/5)

## Définition

Le plus grand commun diviseur (PGCD) de deux nombres entiers non nuls est le
plus grand entier qui les divise en même temps. 

## Exemples:

```C
PGCD(3, 4) = 1,
PGCD(4, 6) = 2,
PGCD(5, 15) = 5.
```

. . .

## Mathématiquement

Décomposition en nombres premiers:

$$
36 = 2^2\cdot 3^2,\quad 90=2\cdot 5\cdot 3^2,
$$
On garde tous les premiers à la puissance la plus basse
$$
PGCD(36, 90)=2^{\min{1,2}}\cdot 3^{\min{2,2}}\cdot 5^{\min{0,1}}=18.
$$

# Le calcul du PGCD (2/5)

## Algorithme

Par groupe de 3 (5-10min):

* réfléchissez à un algorithme alternatif donnant le PGCD de deux nombres;
* écrivez l'algorithme en pseudo-code.

. . .

## Exemple d'algorithme

```C
PGCD(36, 90):
90 % 36 != 0 // otherwise 36 would be PGCD
90 % 35 != 0 // otherwise 35 would be PGCD
90 % 34 != 0 // otherwise 34 would be PGCD
...
90 % 19 != 0 // otherwise 19 would be PGCD
90 % 18 == 0 // The end!
```

* 18 modulos, 18 assignations, et 18 comparaisons.

# Le calcul du PGCD (3/5)

## Transcrivez cet exemple en algorithme (groupe de 3) et codez-le (5-10min)!

. . .

## Optimisation

* Combien d'additions / comparaisons au pire?
* Un moyen de le rendre plus efficace?

. . .

## Tentative de correction

```C
void main() {
   int n = 90, m = 78;
   int gcd = 1;
   for (int div = n; div >= 2; div--) { // div = m, sqrt(n)
      if (n % div == 0 && m % div == 0) {
         gcd = div;
         break;
      }
   }
   printf("Le pgcd de %d et %d est %d\n", n, m, gcd);
}
```

# Le calcul du PGCD (4/5)

## Réusinage: l'algorithme d'Euclide

`Dividende = Diviseur * Quotient + Reste`

```C
PGCD(35, 60):
35 = 60 * 0 + 35 // 60 -> 35, 35 -> 60
60 = 35 * 1 + 25 // 35 -> 60, 25 -> 35
35 = 25 * 1 + 10 // 25 -> 35, 20 -> 25
25 = 10 * 2 +  5 // 10 -> 25, 5  -> 10
10 =  5 * 2 +  0 // PGCD = 5!
```

. . .

## Algorithme

Par groupe de 3 (5-10min):

* analysez l'exemple ci-dessus;
* transcrivez le en pseudo-code.

# Le calcul du PGCD (5/5)

## Pseudo-code

```C
int pgcd(int a, int b) {
    tmp_n = n
    tmp_m = m
    while (tmp_m does not divide tmp_n) {
        tmp   = tmp_n
        tmp_n = tmp_m
        tmp_m = tmp modulo tmp_m
    }
    return tmp_m
}
```

# Le code du PGCD de 2 nombres

## Implémentez le pseudo-code et postez le code sur matrix (5min).

. . .

## Un corrigé possible

```C
#include <stdio.h>
void main() {
   int n = 90;
   int m = 78;
   printf("n = %d et m = %d\n", n, m);
   int tmp_n = n;
   int tmp_m = m;
   while (tmp_n%tmp_m > 0) {
      int tmp = tmp_n;
      tmp_n = tmp_m;
      tmp_m = tmp % tmp_m;
   }
   printf("Le pgcd de %d et %d est %d\n", n, m, tmp_m);
}
```

Original line number Diff line number Diff line
version: "3.3"
services:
    slides:
        #To use dockerfile : build: . 
        image:  omalaspinas/pandoc:latest
        environment:
            USER: 1000
            GROUP: 1000
        user: 1000:1000
        container_name: slides
        volumes:
            - ./:/data
        # entrypoint: ["make", "all"]
        entrypoint: ["make"]
        working_dir: /data
        # user: "$(id -u):$(id -g)"
Original line number Diff line number Diff line
#!/bin/bash

set -e

function get_info() {
    local field=$(echo "$fullName" | sed "$2q;d" $1);
    IFS=$3;
    local field=($field); 
    if [ "${field}" != $5 ]; then
        return 1
    fi
    local field=${field[1]};
    IFS=$4;
    local field=($field);
    local field=${field[1]};
    echo "$field"
}

function fail() {
    printf '%s\n' "$1" >&2 ## Send message to stderr.
    exit "${2-1}" ## Return a code specified by $2, or 1 by default.
}

OIFS=$IFS
NUM_LINE=2
PREFIX=""
@@ -8,36 +29,27 @@ PREFIX=""
classes=()
for i in *.md; do
    [ -f "$i" ] || break
    comp=$(echo "$fullName" | sed "${NUM_LINE}q;d" $i)
    date=$(echo "$fullName" | sed "3q;d" $i)
    IFS=':' 
    comp=($comp); 
    comp=${comp[1]}
    date=($date); 
    date=${date[1]}
    # echo $comp
    IFS='"'
    comp=($comp)
    comp=${comp[1]}
    date=($date); 
    date=${date[1]}
    # echo $comp | awk '{ print substr( $0, 1, length($0)-1 ) }'
    # echo $comp
    # date=sed "${NUM_LINE}q;d" $i
    date="$(get_info $i 3 ":" '"' "date")"
    if [ "$date" == 1 ]; then
        fail "Error date field not found"
    fi
    comp="$(get_info $i 2 ":" '"' "title")"
    if [ "$comp" == 1 ]; then
        fail "Error title field not found"
    fi
    i="${i%.*}"
    class="[${date} ${comp}](${PREFIX}${i}.pdf)"
    classes+=($class)
    # echo "[${date} ${comp}](${PREFIX}${i}.pdf)" >> index.md
    class="[${date}: ${comp}](${PREFIX}${i}.pdf)"
    classes+=("$class")
done
IFS=$'\n'
classes=($(sort <<<"${classes[*]}"))
date=$(date '+%Y-%m-%d')
echo "---" >> index.md
echo "title: Slides du cours d'Algorithmique" >> index.md
echo "date: ${date}" >> index.md
echo "title: \"Slides du cours d'algorithmique\"" >> index.md
echo "date: \"${date}\"" >> index.md
echo "---" >> index.md
echo "" >> index.md
echo "# Tous les slides du cours d'Algorithmique" >> index.md
echo "# Tous les slides du cours d'algorithmique" >> index.md
echo "" >> index.md
for i in ${classes[*]}; do
    echo "* $i" >> index.md
+21 −38
Original line number Diff line number Diff line
---
title: "Introduction générale"
date: "2020-09-16"
date: "2025-09-16"
---

# La hotline
@@ -11,59 +11,42 @@ Paul Albuquerque paul.albuquerque@hesge.ch B410
Orestis Malaspinas     orestis.malaspinas@hesge.ch       A401
--------------------   ------------------------------    --------------------

Utilisez le libre service (l'horaire sera fixé prochainement).
- Utilisez le libre service (l'horaire sera fixé prochainement).
- On va intensivement utiliser *Element*, installez le et utilisez le!
- Espace de discussion Matrix: <https://rb.gy/ku5es>, installez [element.io](https://element.io).

Salon de discussion [Matrix](https://matrix.to/#/!tuZtXjUSPbnRfBsFXv:matrix.org?via=matrix.org), installez [element.io](https://element.io).

![](figs/matrix.png){width=20%}
    ![](figs/matrix_qr.png){width=20%}

# Cyberlearn

Tout le contenu de ce qu'on raconte se trouve sur cyberlearn:

- Algorithmes et structures de données
  - <https://cyberlearn.hes-so.ch/course/view.php?id=13941>
  - Clé d'inscription: algo_2020_21
  - <https://cyberlearn.hes-so.ch/course/view.php?id=7276>
  - Clé d'inscription: algo_2025_26

- Programmation séquentielle en C
  - <https://cyberlearn.hes-so.ch/course/view.php?id=7282>
  - Clé d'inscription: prog_seq_2025_26

- Programmation Sequentielle en C
  - <https://cyberlearn.hes-so.ch/course/view.php?id=12399>
  - Clé d'inscription: PS_2018

# Organisation du module

* Deux cours, 50% chacun.
1. Algorithmes et structures de données:
## Cinq cours, 20% chacun.

1. Algorithmes et structures de données (2 semestres):
    * 1er semestre:
        * bases de programmation en C jusqu'à Noël.
        * bases de programmation en C jusqu'à Noël,
        * algorithmique jusqu'à fin janvier.
    * 2e semestre:
    * 2ème semestre:
        * algorithmique.
    * Deux évaluations écrites par semestre.
2. Programmation séquentielle en C
    * Deux évaluations écrites par semestre (1er sem.: novembre et janvier).
2. Programmation séquentielle en C (2 semestres)
    * Familiarisation avec l'environnement Linux.
    * Travaux pratiques en C.
    * Apprentissage du gestionnaire de versions: git.
    * Plusieurs "petits" exercices illustrant les concepts d'algorithmique 
      (1-2 séances).
    * Évaluations:
        * Un projet de programmation.
        * Une évaluation machine.

# Sondage: expérience de programmation

## [Sondage: expérience de linux](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1291283)

## [Sondage: expérience de programmation](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1035242)

**Installez un lecteur de QR code s'il-vous-plaît.**

# Questions?

- N'hésitez pas à poser des *questions*, nous sommes là pour ça! [^1]
- Ne restez pas coincés pendant des jours sur un problème.
- Utilisez le *libre-service*!
- N'hésitez pas à faire des *retours*: *négatifs* ou *positifs*.

[^1]: Chaque étudiant·e·s a un quota de 5 questions par semestre.
    * Plusieurs exercices illustrant les concepts d'algorithmique.
    * Évaluations (4 tests machine).
3. Programmation système (semestre de printemps)

Original line number Diff line number Diff line
---
subtitle: "Algorithmique et structures de données, 2021-2022"
author: "Paul Albuquerque (B410), Pierre Künzli et Orestis Malaspinas (A401), ISC, HEPIA"
institute: En partie inspirés des supports de cours de P. Albuquerque
subtitle: "Algorithmique et structures de données, 2025-2026"
author: "P. Albuquerque (B410) et O. Malaspinas (A401), ISC, HEPIA"
institute: En partie inspiré des supports de cours de P. Albuquerque
lang: fr-CH
revealjs-url: /reveal.js
mathjaxurl: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML"

slides_2021/.gitignore

0 → 100644
+6 −0
Original line number Diff line number Diff line
*.pdf
*.err
*.markdown
*.html
index.md
.puppeteer.json

slides_2021/Makefile

0 → 100644
+71 −0
Original line number Diff line number Diff line
PDFOPTIONS = -t beamer
# PDFOPTIONS += -F pantable
PDFOPTIONS += -F mermaid-filter
PDFOPTIONS += --highlight-style my_highlight.theme
PDFOPTIONS += --pdf-engine xelatex
PDFOPTIONS += -V theme:metropolis
PDFOPTIONS += -V themeoptions:numbering=none -V themeoptions:progressbar=foot
PDFOPTIONS += -V fontsize=smaller
PDFOPTIONS += -V urlcolor=blue

REVEALOPTIONS = -t revealjs
REVEALOPTIONS += -F mermaid-filter
REVEALOPTIONS += --self-contained
REVEALOPTIONS += -V revealjs-url=reveal.js
REVEALOPTIONS += -V theme=white
REVEALOPTIONS += -V width=1920
REVEALOPTIONS += -V margin=0
REVEALOPTIONS += --slide-level=1

MD=$(wildcard *.md) # Tous les fichiers .md
PDF=$(MD:%.md=%.pdf) # Pour les fichier pdf on transforme .md -> .pdf
HTML=$(MD:%.md=%.html) # Pour les fichier html on transforme .md -> .html
MARKDOWN=$(MD:%.md=%.markdown) # Pour les fichier markdown on transforme .md -> .markdown
CHROMIUM:=$(shell which chromium || which chromium-browser)

all: puppeteer $(PDF) 
# all: puppeteer $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.pdf

docker: docker-compose.yml
	docker-compose run slides make puppeteer -k || true
	docker-compose run slides make all -k || true

docker_clean: docker-compose.yml
	docker-compose run slides make clean -k || true

puppeteer:
	@echo "Setting chromium to $(CHROMIUM) for puppeteer"
	@echo -e "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json

index:
	rm -f index.md
	./gen_index.sh

markdown: $(MARKDOWN) # La markdown les cibles %.markdown

%.pdf: %.md metadata.yaml # %.pdf (chaque fichier %.md génère un fichier avec le même nom mais l'extension .pdf et la dépendance metadata.yaml)
	pandoc -s $(OPTIONS) $(PDFOPTIONS) -o $@ $^

%.html: %.md metadata.yaml
	pandoc -s $(OPTIONS) $(REVEALOPTIONS) -o $@ $^

%.markdown: %.md metadata.yaml yq
	sed '1 { /^---/ { :a N; /\n---/! ba; d} }' $< > no_header
	grep -v -F -x -f  no_header $< > header.yaml
	echo "---" > tmp.yaml
	./yq_linux_amd64 merge metadata.yaml header.yaml >> tmp.yaml
	cat tmp.yaml no_header > $@
	rm no_header header.yaml tmp.yaml

yq: # On peut même télécharger un petit programme avec notre makefile
	wget -nc https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64
	chmod "u+x" yq_linux_amd64 

deploy: all 
	mkdir -p algo_cours
	cp *.pdf algo_cours

clean:
	rm -f *.html *.pdf *.markdown yq_linux_amd64* index.md .puppeteer.json

.PHONY:	clean index puppeteer yq

slides_2021/cours_1.md

0 → 100644
+693 −0
Original line number Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2021-09-22"
---

# Qu'est-ce qu'un algorithme?

## Définition informelle (recette)

* des entrées (les ingrédients, le matériel utilisé) ;
* des instructions élémentaires simples (frire, flamber, etc.), dont les 
  exécutions dans un ordre précis amènent au résultat voulu ;
* un résultat : le plat préparé.

. . .

## Histoire et étymologie

- Existent depuis 4500 ans au moins (algorithme de division, crible 
  d'Eratosthène).
- Le mot algorithme est dérivé du nom du mathématicien perse
    *Muḥammad ibn Musā al-Khwārizmī*, qui a été "latinisé" comme 
    *Algoritmi*.

. . .

## Définition formelle

En partant d'un état initial et d'entrées (peut-être vides), une séquence finie 
d'instruction bien définies (ordonnées) implémentables sur un ordinateur, afin 
de résoudre typiquement une classe de problèmes ou effectuer un calcul.

# Notions de base d'algorithmique

## Variable

. . .

* Paire: identifiant - valeur (assignation);

## Séquence d'instructions / expressions

. . .

* Opérateurs (arthimétiques / booléens)
* Boucles;
* Structures de contrôle;
* Fonctions;


# Algorithme de vérification qu'un nombre est premier (1/3)

Nombre premier: nombre possédant deux diviseurs entiers distincts.

. . .

## Algorithme naïf (problème)

```C
est_premier(nombre) {
    si {
        pour tout i, t.q. 1 < i < nombre {
            i ne divise pas nombre
        }
    } alors vrai
    sinon faux
}
```

. . .

## Pas vraiment un algorithme: pas une séquence ordonnée et bien définie

. . .

## Problème: Comment écrire ça sous une forme algorithmique?

# Algorithme de vérification qu'un nombre est premier (2/3)

## Algorithme naïf (une solution)

```C
est_premier(nombre) { // fonction
    soit i := 2;       // variable, type, assignation
    tant que i < nombre { // boucle
        si nombre modulo i = 0 { // expression typée
            retourne faux    // expression typée
        }
        i := i + 1
    }
    retourne vrai // expression typée
```

# Algorithme de vérification qu'un nombre est premier (3/3)

## Algorithme naïf (une solution en C)

```C
bool est_premier(int nombre) {
    int i; // i est un entier
    i = 2; // assignation i à 2
    while (i < nombre) { // boucle avec condition
        if (0 == nombre % i) { // is i divise nombre
            return false; // i n'est pas premier
        }
        i += 1; // sinon on incrémente i
    }
    return true;
}
```

. . .

## Exercice: Comment faire plus rapide?

# Génération d'un exécutable

- Pour pouvoir être exécuté un code C doit être d'abord compilé (avec `gcc` ou `clang`).
- Pour un code `prog.c` la compilation "minimale" est

    ```bash
    $ gcc prog.c
    $ ./a.out # exécutable par défaut
    ```

- Il existe une multitude d'options de compilation:

    ```bash
    $ gcc -O1 -std=c11 -Wall -Wextra -g porg.c -o prog -fsanitize=address 
    -fsanitize=leak -fsanitize=undefined
    ```
    1. `-std=c11` utilisation de C11.
    2. `-Wall et -Wextra` activation des warnings.
    3. `-fsanitize=…`  contrôles d’erreurs à l’exécution (coût en performance).
    4. `-g` symboles de débogages sont gardés.
    5. `-o` défini le fichier exécutable à produire en sortie.
    6. `-O1`, `-O2`, `-O3`: activation de divers degrés d'optimisation



# La simplicité de C?

## 32 mots-clé et c'est tout

---------------- -------------- ---------------- ---------------
`auto`{.C}       `double`{.C}   `int`{.C}        `struct`{.C}   
`break`{.C}      `else`{.C}     `long`{.C}       `switch`{.C}   
`case`{.C}       `enum`{.C}     `register`{.C}   `typedef`{.C}  
`char`{.C}       `extern`{.C}   `return`{.C}     `union`{.C}    
`const`{.C}      `float`{.C}    `short`{.C}      `unsigned`{.C} 
`continue`{.C}   `for`{.C}      `signed`{.C}     `void`{.C}
`default`{.C}    `goto`{.C}     `sizeof`{.C}     `volatile`{.C}
`do`{.C}         `if`{.C}       `static`{.C}     `while`{.C}
---------------- -------------- ---------------- ---------------

# Déclaration et typage

En C lorsqu'on veut utiliser une variable (ou une constante), on doit déclarer son type

```C
const double two = 2.0; // déclaration et init.
int x;   // déclaration (instruction)
char c;  // déclaration (instruction)
x = 1;   // affectation (expression)
c = 'a'; // affectation (expression)
int y = x; // déclaration et initialisation en même temps
int a, b, c; // déclarations multiples
a = b = c = 1; // init. multiples
```

# Les variables (1/2)

## Variables et portée

- Une variable est un identifiant, qui peut être liée à une valeur (un expression).
- Une variable a une **portée** qui définit où elle est *visible* (où elle peut être accédée).
- La portée est **globale** ou **locale**.
- Une variable est **globale** est accessible à tout endroit d'un programme et doit être déclarée en dehors de toute fonction.
- Une variable est **locale** lorsqu'elle est déclarée dans un **bloc**, `{...}`{.C}.
- Une variable est dans la portée **après** avoir été déclarée.

# Les variables (2/2)

## Exemple 

```C
float max; // variable globale accessible partout
int foo() {
    // max est visible ici
    float a = max; // valide
    // par contre les varibles du main() ne sont pas visibles
}
int main() {
    // max est visible ici
    int x = 1; // x est locale à main
    {
        // x est visible ici, y pas encore
        // on peut par exemple pas faire x = y;
        int y = 2;
    } // y est détruite à la sortie du bloc
} // x est à la sortie de main

```

<!-- TODO: quiz, compile, compile pas -->
<!-- ```C
int main() {
    global = 1;
} // COMPILE PAS
```

```C
int main() {
    int global = 1;
    {
        printf("global = %d", global);
    }
} // COMPILE
```

```C
int local;

int main() {
    local = 1;
    {
        printf("local = %d", local);
    }
} // COMPILE
```

```C
#include <stdio.h>
int local = 0;

int main() {
    int local = -1;
    {
        int local = 1;
        printf("local = %d\n", local);
    }
} // COMPILE
``` -->

# Quiz: compile ou compile pas?

## [Quiz: compile ou compile pas](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033948)

# Types de base (1/4)

## Numériques

Type                               Signification (**gcc pour x86-64**)            
---------------------------------- ---------------------------------------------
`char`{.C}, `unsigned char`{.C}    Entier signé/non-signé 8-bit
`short`{.C}, `unsigned short`{.C}  Entier signé/non-signé 16-bit
`int`{.C}, `unsigned int`{.C}      Entier signé/non-signé 32-bit
`long`{.C}, `unsigned long`{.C}    Entier signé/non-signé 64-bit
`float`{.C}                        Nombre à virgule flottante, simple précision
`double`{.C}                       Nombre à virgule flottante, double précision
---------------------------------- ---------------------------------------------

**La signification de `short`{.C}, `int`{.C}, ... dépend du compilateur et de l'architecture.**

# Types de base (2/4)

Voir `<stdint.h>` pour des représentations **portables**

Type                               Signification
---------------------------------- ---------------------------------------------
`int8_t`{.C}, `uint8_t`{.C}        Entier signé/non-signé 8-bit
`int16_t`{.C}, `uint16_t`{.C}      Entier signé/non-signé 16-bit
`int32_t`{.C}, `uint32_t`{.C}      Entier signé/non-signé 32-bit
`int64_t`{.C}, `uint64_t`{.C}      Entier signé/non-signé 64-bit
---------------------------------- ---------------------------------------------

. . .

## Prenez l'habitude d'utiliser ces types-là!

# Types de base (3/4)

## Booléens

- Le ANSI C n'offre pas de booléens.
- L'entier `0`{.C} signifie *faux*, tout le reste *vrai*.
- Depuis C99, la librairie `stdbool` met à disposition un type `bool`{.C}.
- En réalité c'est un entier:
  - $1 \Rightarrow$ `true`{.C}
  - $0 \Rightarrow$ `false`{.C}
- On peut les manipuler comme des entier (les sommer, les multiplier, ...).

# Quiz: booléens

## [Quiz: booléens](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1032492)

<!-- TODO Quiz en ligne -->
<!-- ```C
if (42) { /* vrai */ }

int x = 100;
if (x == 4) { /* faux */ }
if (x) { /* vrai */ }

int x = 100;
while (x−−) { /* répète tant que x est différent de 0 */ }

if (0) { /* faux */ }
if (i = 4) { /* vrai */ }
if (i = 0) { /* faux */ }

#include <stdbool.h>

bool x = true;
if (x) { /* vrai */ }
``` -->

# Types de base (4/4)

## Conversions

- Les conversions se font de manière:
  - Explicite:
    ```C
    int a = (int)2.8;
    double b = (double)a;
    int c = (int)(2.8+0.5);
    ```
  - Implicite:
    ```C
    int a = 2.8; // warning, si activés, avec clang
    double b = a + 0.5;
    char c = b; // pas de warning...
    int d = 'c';
    ```

# Quiz: conversions

## [Quiz: conversions](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033446)

<!-- TODO Quiz en ligne -->
<!-- ```C
int a = (int)2.8; // 2

double b = 2.85;
int c = b + 0.5; // 3

int d = a + 0.5; // 2

bool d = 2.78; // 1
bool e = 1.0; // 1
``` -->

# Expressions et opérateurs (1/6)

Une expression est tout bout de code qui est **évalué**.

## Expressions simples

- Pas d'opérateurs impliqués.
- Les littéraux, les variables, et les constantes.

```C
const int L = -1; // 'L' est une constante, -1 un littéral
int x = 0;        // '0' est un litéral
int y = x;        // 'x' est une variable
int z = L;        // 'L' est une constante
```

## Expressions complexes

- Obtenues en combinant des *opérandes* avec des *opérateurs*

```C
int x;     // pas une expression (une instruction)
x = 4 + 5; // 4 + 5 est une expression
           // dont le résultat est affecté à 'x'
```

# Expressions et opérateurs (2/6)

## Opérateurs relationnels

Opérateurs testant la relation entre deux *expressions*:

  - `(a opérateur b)` retourne `1`{.C} si l'expression s'évalue à `true`{.C}, `0`{.C} si l'expression s'évalue à `false`{.C}.

| Opérateur | Syntaxe      | Résultat             |
|-----------|--------------|----------------------|
| `<`{.C}   | `a < b`{.C}  | 1 si a <  b; 0 sinon |
| `>`{.C}   | `a > b`{.C}  | 1 si a >  b; 0 sinon |
| `<=`{.C}  | `a <= b`{.C} | 1 si a <= b; 0 sinon |
| `>=`{.C}  | `a >= b`{.C} | 1 si a >= b; 0 sinon |
| `==`{.C}  | `a == b`{.C} | 1 si a == b; 0 sinon |
| `!=`{.C}  | `a != b`{.C} | 1 si a != b; 0 sinon |

# Expressions et opérateurs (3/6)

## Opérateurs logiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `&&`{.C}  | `a && b`{.C} | ET logique           |
| `||`{.C}  | `a || b`{.C} | OU logique           |
| `!`{.C}   | `!a`{.C}     | NON logique          |

# Quiz: opérateurs logiques

## [Quiz: opérateurs logiques](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033629)

<!-- TODO: Quiz -->
<!-- ```C
1 && 0 == 0
7 && 3 == 1
4 || 3 == 1
!34 == 0
!0 == 1

Soit n un unsigned char initialisé à 127:
!n == 0
``` -->

# Expressions et opérateurs (4/6)

## Opérateurs arithmétiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `+`{.C}   | `a + b`{.C}  | Addition             |
| `-`{.C}   | `a - b`{.C}  | Soustraction         |
| `*`{.C}   | `a * b`{.C}  | Multiplication       |
| `/`{.C}   | `a / b`{.C}  | Division             |
| `%`{.C}   | `a % b`{.C}  | Modulo               |

# Expressions et opérateurs (5/6)

## Opérateurs d'assignation

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `=`{.C}   | `a = b`{.C}  | Affecte la valeur `b` à la variable `a`     |
|           |              | et retourne la valeur de `b`                |
| `+=`{.C}  | `a += b`{.C} | Additionne la valeur de `b` à `a` et        |
|           |              | assigne le résultat à `a`.                  |
| `-=`{.C}  | `a -= b`{.C} | Soustrait la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `*=`{.C}  | `a *= b`{.C} | Multiplie la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `/=`{.C}  | `a /= b`{.C} | Divise la valeur de `b` à `a` et            |
|           |              | assigne le résultat à `a`.                  |
| `%=`{.C}  | `a %= b`{.C} | Calcule le modulo la valeur de `b` à `a` et |
|           |              | assigne le résultat à `a`.                  |

# Expressions et opérateurs (6/6)

## Opérateurs d'assignation (suite)

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `++`{.C}  | `++a`{.C}    | Incrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a += 1`).            |
| `--`{.C}  | `--a`{.C}    | Décrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a -= 1`).            |
| `++`{.C}  | `a++`{.C}    | Retourne `a`{.C} et incrémente `a` de 1.    |
| `--`{.C}  | `a--`{.C}    | Retourne `a`{.C} et décrémente `a` de 1.    |


# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (1/2)

## Syntaxe

```C
if (expression) {
    instructions;
} else if (expression) { // optionnel
                         // il peut y en avoir plusieurs
    instructions;
} else {
    instructions; // optionnel
}
```

```C
if (x) { // si x s'évalue à `vrai`
    printf("x s'évalue à vrai.\n");
} else if (y == 8) { // si y vaut 8
    printf("y vaut 8.\n");
} else {
    printf("Ni l'un ni l'autre.\n");
}
```

# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (2/2)

## Pièges

```C
int x, y;
x = y = 3;
if (x = 2)
    printf("x = 2 est vrai.\n");
else if (y < 8)
    printf("y < 8.\n");
else if (y == 3)
    printf("y vaut 3 mais cela ne sera jamais affiché.\n");
else
    printf("Ni l'un ni l'autre.\n");
    x = -1; // toujours évalué
```

# Quiz: `if ... else`{.C}

## [Quiz: `if ... else`{.C}](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033916)


# Structures de contrôle: `while`{.C}

## La boucle `while`{.C}

```C
while (condition) {
    instructions;
}
do {
    instructions;
} while (condition);
```

## La boucle `while`{.C}, un exemple

```C
int sum = 0; // syntaxe C99
while (sum < 10) {
    sum += 1;
}
do {
    sum += 10;
} while (sum < 100)
```

# Structures de contrôle: `for`{.C}

## La boucle `for`{.C}

```C
for (expression1; expression2; expression3) {
    instructions;
}
```

## La boucle `for`{.C}

```C
int sum = 0; // syntaxe C99
for (int i = 0; i < 10; i++) {
    sum += i;
}

for (int i = 0; i != 1; i = rand() % 4) { // ésotérique
    printf("C'est plus ésotérique.\n");
}
```

# Exercice: la factorielle

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un pseudo-code

. . .

```C
int factorielle(int n) {
    i = 1;
    fact = 1;
    pour i <= n {
        fact *= i;
        i += 1;
    }
}
```

# Exercice: la factorielle

\footnotesize

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un code en C

Quand vous avez fini postez le code sur le salon matrix.

. . .

```C
#include <stdio.h>
int main() {
   int nb = 10;
   int fact = 1;
   int iter = 2;
   while (iter <= nb) {
      fact *= iter;
      iter++;
   }
}
```

. . .

## Comment améliorer ce code? (notez ça sur une feuille)


# Entrées/sorties: `printf()`{.C} (1/2)

## Généralités

- La fonction `printf()`{.C} permet d'afficher du texte sur le terminal:

    ```C
    int printf(const char *format, ...);
    ```
- Nombre d'arguments variables.
- `format`{.C} est le texte, ainsi que le format (type) des variables à afficher.
- Les arguments suivants sont les expressions à afficher.

# Entrées/sorties: `printf()`{.C} (2/2)

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Hello world.\n");
    int val = 1;
    printf("Hello world %d time.\n", val);
    printf("%f squared is equal to %f.\n", 2.5, 2.5*2.5);
    return EXIT_SUCCESS;
}
```

# Entrées/sorties: `scanf()`{.C} (1/2)

## Généralités

- La fonction `scanf()`{.C} permet de lire du texte formaté entré au clavier:

    ```C
    int scanf(const char *format, ...);
    ```

- `format`{.C} est le format des variables à lire (comme `printf()`{.C}).
- Les arguments suivants sont les variables où sont stockées les valeurs lues.

# Entrées/sorties: `scanf()`{.C} (2/2)

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Enter 3 numbers: \n");
    int i, j, k;
    scanf("%d %d %d", &i, &j, &k);
    printf("You entered: %d %d %d\n", i, j, k);
    
    return EXIT_SUCCESS;
}
```

# Exercice: la factorielle en mieux

## Individuellement

1. Ajoutez des fonctionnalités à votre code.
2. Écrivez l'algorithme de calcul de deux façon différentes.
3. Pour celles et ceux qui ont fini pendant que les autres essaient: faites-le 
   en récursif (sans aide).

. . .

## Postez vos solutions sur matrix!

Original line number Diff line number Diff line
---
title: "Le tri par tas"
title: "Arbres et tri par tas"
date: "2022-03-02"
patat:
  eval:
    tai:
      command: fish
      fragment: false
      replace: true
    ccc:
      command: fish
      fragment: false
      replace: true
  images:
    backend: auto
---

# Un joli site

## Visualisation d'algorithmes

* <https://visualgo.net/>
* Allons nous rafraîchir la mémoire sur l'insertion / recherche dans un arbre
  binaire.



# Pseudocode d'insertion (1/2)

* Deux parties:
    * Recherche le parent où se passe l'insertion.
    * Ajout du fils dans l'arbre.

## Recherche du parent

```
arbre position(arbre, clé)
    si est_non_vide(arbre)
        si clé < clé(arbre)
            suivant = gauche(arbre)
        sinon
            suivant = droite(arbre)
        tant que clé(arbre) != clé && est_non_vide(suivant)
            arbre = suivant
            si clé < clé(arbre)
                suivant = gauche(arbre)
            sinon
                suivant = droite(arbre)
            
    retourne arbre
```

# Pseudocode d'insertion (2/2)

* Deux parties:
    * Recherche de la position.
    * Ajout dans l'arbre.

## Ajout du fils

```
ajout(arbre, clé)
    si est_vide(arbre)
        arbre = noeud(clé)
    sinon
        arbre = position(arbre, clé)
        si clé < clé(arbre)
            gauche(arbre) = noeud(clé)
        sinon si clé > clé(arbre)
            droite(arbre) = noeud(clé)
        sinon
            retourne
```

# Code d'insertion en C (1/2)

## Recherche du parent (ensemble)

. . .

```C
tree_t position(tree_t tree, key_t key) {
    tree_t current = tree;
    if (NULL != current) {
        tree_t subtree = key > current->key ? current->right :
        current->left;
        while (key != current->key && NULL != subtree) {
            current = subtree;
            subtree = key > current->key ? current->right :
            current->left;
        }
    }
    return current;
}
```

# Code d'insertion en C (2/2)

## Ajout du fils (ensemble)

\scriptsize

* 2 cas: arbre vide ou pas.
* on retourne un pointeur vers le noeud ajouté (ou `NULL`)

. . .

```C
tree_t add_key(tree_t *tree, key_t key) {
    node_t *new_node = calloc(1, sizeof(*new_node)); // nouveauté!
    new_node->key = key;
    if (NULL == *tree) {
        *tree = new_node;
    } else {
        tree_t subtree = position(*tree, key);
        if (key == subtree->key) {
            return NULL;
        } else {
            if (key > subtree->key) {
                subtree->right = new_node;
            } else {
                subtree->left = new_node;
            }
        }
    }
    return new_node;
}
```

# Une nouvelle corde à votre arc!

\footnotesize

```C
void *calloc(size_t nmemb, size_t size); // man 3 calloc
```

```
$ man 3 calloc

The calloc() function allocates memory for an array of nmemb elements
of size bytes each and returns a pointer  to  the  allocated  memory.
The  memory is set to zero.  If nmemb or size is 0, then calloc() re‐
turns either NULL, or a unique pointer value that can later  be  suc‐
cessfully  passed to free().  If the multiplication of nmemb and size
would result in integer overflow, then calloc() returns an error.  By
contrast,  an integer overflow would not be detected in the following
call to malloc(), with the result that an incorrectly sized block  of
memory would be allocated:

   malloc(nmemb * size);
```

# La suppression de clé


. . .

::: columns

:::: column

## Cas simples: 

* le noeud est absent, 
* le noeud est une feuille
* le noeuds a un seul fils.

## Une feuille (le 19 p.ex.).

```{.mermaid format=pdf width=400 loc=figs/}
flowchart TB;
    10-->20;
    10-->5
    20-->21
    20-->19
```

::::

:::: column

## Un seul fils (le 20 p.ex.).

```{.mermaid format=pdf width=400 loc=figs/}
flowchart TB;
    10-->20;
    10-->5
    20-->25
    20-->18
    25-->24
    25-->30
    5-->4;
    5-->8;
    style 18 fill:#fff,stroke:#fff,color:#fff
```

## Dans tous les cas

* Chercher le noeud à supprimer: utiliser `position()`.

::::

:::

# La suppression de clé


::: columns

:::: column

## Cas compliqué

* Le noeud à supprimer à (au moins) deux descendants (10).

```{.mermaid format=pdf width=400 loc=figs/}
flowchart TB;
    10-->20;
    10-->5
    20-->25
    20-->18
    25-->24
    25-->30
    5-->4;
    5-->8;
```

::::

:::: column

* Si on enlève 10 il se passe quoi?
* On peut pas juste enlever `10` et recoller...
* Proposez une solution bon sang!

. . .

## Solution

* Échange de la valeur à droite dans le sous-arbre de gauche ou
  ...
* de la valeur de gauche dans le sous-arbre de droite!
* Puis, on retire le noeud.

::::

:::

# Le pseudo-code  de la suppression

## Pour une feuille ou absent (ensemble)

```
arbre suppression(arbre, clé)
    sous_arbre = position(arbre, clé)
    si est_vide(sous_arbre) ou clé(sous_arbre) != clé
        retourne vide
    sinon
        si est_feuille(sous_arbre) et clé(sous_arbre) == clé
            nouvelle_feuille = parent(arbre, sous_arbre)
            si est_vide(nouvelle_feuill)
                arbre = vide
            sinon 
                si gauche(nouvelle_feuille) == sous_arbre 
                    gauche(nouvelle_feuille) = vide
                sinon
                    droite(nouvelle_feuille) = vide
        retourne sous_arbre
```

# Il nous manque le code pour le `parent`
## Pseudo-code pour trouver le parent (5min -> matrix)

. . .

```
arbre parent(arbre, sous_arbre)
    si est_non_vide(arbre)
        actuel = arbre
        parent = actuel
        clé = clé(sous_arbre)
        faire
            si (clé != clé(actuel))
                parent = actuel
                si clé < clé(actuel)
                    actuel = gauche(actuel)
                sinon
                    actuel = droite(actuel)
            sinon
                retour parent
        tant_que (actuel != sous_arbre)
    retourne vide
```

# Le pseudo-code  de la suppression

## Pour un seul enfant (5min -> matrix)

. . .

```
arbre suppression(arbre, clé)
    sous_arbre = position(arbre, clé)
    si est_vide(gauche(sous_arbre)) ou est_vide(droite(sous_arbre))
        parent = parent(arbre, sous_arbre)
        si est_vide(gauche(sous_arbre))
            si droite(parent) == sous_arbre
                droite(parent) = droite(sous_arbre)
            sinon
                gauche(parent) = droite(sous_arbre)
        sinon
            si droite(parent) == sous_arbre
                droite(parent) = gauche(sous_arbre)
            sinon
                gauche(parent) = gauche(sous_arbre)
        retourne sous_arbre
```


# Le pseudo-code  de la suppression

\footnotesize

## Pour au moins deux enfants (ensemble)

```
arbre suppression(arbre, clé)
    sous_arbre = position(arbre, clé) # on revérifie pas que c'est bien la clé
    si est_non_vide(gauche(sous_arbre)) et est_non_vide(droite(sous_arbre))
        max_gauche = position(gauche(sous_arbre), clé)
        échange(clé(max_gauche), clé(sous_arbre))
        suppression(gauche(sous_arbre), clé)
```

# Exercices (poster sur matrix)

1. Écrire le pseudo-code de l'insertion purement en récursif.

. . .

```
arbre insertion(arbre, clé)
    si est_vide(arbre)
        retourne noeud(clé)

    si (clé < arbre->clé)
        gauche(arbre) = insert(gauche(arbre), clé)
    sinon
        droite(arbre) = insert(droite(arbre), clé)
    retourne arbre
```

# Exercices (poster sur matrix)

2. Écrire le pseudo-code de la recherche purement en récursif.

. . .

```
bool recherche(arbre, clé)
    si est_vide(arbre)
        retourne faux // pas trouvée
    si clé(arbre) == clé
        retourne vrai // trouvée
    si clé < clé(arbre)
        retourne recherche(gauche(arbre), clé)
    sinon
        retourne recherche(droite(arbre), clé)
```

# Exercices (à la maison)

3. Écrire une fonction qui insère des mots dans un arbre et ensuite affiche
   l'arbre.

# Trier un tableau à l'aide d'un arbre binaire

* Tableau représenté comme un arbre binaire.
@@ -300,11 +671,11 @@ graph TD;
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((5));
    id0-->id2((8));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((8));
    id2-->id6((5));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
@@ -364,11 +735,11 @@ graph TD;
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((16))-->id1((12));
    id0-->id2((5));
    id0-->id2((8));
    id1-->id3((1));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((8));
    id2-->id6((5));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
@@ -408,3 +779,423 @@ graph TD;
                *        *               *
        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
```

* L'arbre est un tas.

# Exemple de tri par tas (6/N)

```
        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `16` (`max` de l'arbre) avec `4`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((4))-->id1((12));
    id0-->id2((8));
    id1-->id3((10));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((6));
```

::::

:::: column

**But:** Trier les tas.

* `4 <=> max(4, 12, 8)`.
* `4 <=> max(4, 10, 7)`.
* `4 <=> max(4, 1, 6)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((12))-->id1((10));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((4));
```

::::

:::

```
        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
```


# Exemple de tri par tas (7/N)

```
        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `12` (`max` de l'arbre) avec `4`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((4))-->id1((10));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((  ));
    style id8 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas.

* `4 <=> max(4, 10, 8)`.
* `4 <=> max(4, 6, 7)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((10))-->id1((7));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((  ));
    style id8 fill:#fff,stroke:#fff
```

::::

:::

```
        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
```

# Exemple de tri par tas (8/N)

```
        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `10` (`max` de l'arbre) avec `1`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((7));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((5));
```

::::

:::: column

**But:** Trier les tas.

* `1 <=> max(1, 7, 8)`.
* `5 <=> max(1, 2, 5)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((8))-->id1((7));
    id0-->id2((5));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((1));
```

::::

:::

```
        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
```

# Exemple de tri par tas (9/N)

```
        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `8` (`max` de l'arbre) avec `1`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((7));
    id0-->id2((5));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((  ));
    style id6 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas.

* `1 <=> max(1, 7, 5)`.
* `1 <=> max(1, 6, 4)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((7))-->id1((6));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((  ));
    style id6 fill:#fff,stroke:#fff
```

::::

:::

```
        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
```

# Exemple de tri par tas (10/N)

```
        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `7` (`max` de l'arbre) avec `2`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((2))-->id1((6));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((4));
```

::::

:::: column

**But:** Trier les tas.

* `2 <=> max(2, 6, 5)`.
* `2 <=> max(2, 1, 4)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((6))-->id1((4));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((2));
```

::::

:::

```
        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
```

# Exemple de tri par tas (11/N)

```
        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `6` (`max` de l'arbre) avec `2`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((2))-->id1((4));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((  ));
    style id4 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas.

* `2 <=> max(2, 4, 5)`.
* `2 <=> max(2, 1, 4)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((5))-->id1((4));
    id0-->id2((2));
    id1-->id3((1));
    id1-->id4((  ));
    style id4 fill:#fff,stroke:#fff
```

::::

:::

```
        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
```

# Exemple de tri par tas (12/N)

```
        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `5` (`max` de l'arbre) avec `1`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((4));
    id0-->id2((2));
```

::::

:::: column

**But:** Trier les tas.

* `1 <=> max(1, 4, 2)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((4))-->id1((1));
    id0-->id2((2));
```

::::

:::

```
        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
```

# Exemple de tri par tas (13/N)

```
        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `4` (`max` de l'arbre) avec `2`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((2))-->id1((1));
    id0-->id2(( ));
    style id2 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas. Plus rien à trier

* On fait les 2 dernières étapes en vitesse.
* Échange `2` avec `1`.
* Il reste que `1`. GGWP!


::::

:::

```
        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
```

# Exercice (10min)

* Trier par tas le tableau

```
        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
```

* Mettez autant de détails que possible.
* Que constatez-vous?
* Postez le résultat sur matrix.

+1129 −0
Original line number Diff line number Diff line
---
title: "Tri par tas et arbres AVL"
date: "2022-03-09"
patat:
  eval:
    tai:
      command: fish
      fragment: false
      replace: true
    ccc:
      command: fish
      fragment: false
      replace: true
  images:
    backend: auto
---

# Questions sur les notions du dernier cours

* Comment représenter un tableau sous forme d'arbre binaire?

. . .

* Qu'est-ce qu'un tas?

# Exemple de tri par tas (1/N)

```
        | 1 | 16 | 5 | 12 | 4 | 2 | 8 | 10 | 6 | 7 |
```

::: columns

:::: column

* Quel est l'arbre que cela représente?

. . .

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((5));
    id1-->id3((12));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((8));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((7));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Transformer l'arbre en tas.

* On commence à l'indice $N/2 = 5$: `4`.
* `7 > 4` (enfant `>` parent).
* intervertir `4` et `7`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((5));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((8));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::

. . .

```
                            *                    *
        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
```

# Exemple de tri par tas (2/N)

```
        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
```

::: columns

:::: column

**But:** Transformer l'arbre en tas.

* On continue à l'indice $N/2-1 = 4$: `12`.
* Déjà un tas, rien à faire.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((5));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((8));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Transformer l'arbre en tas.

* On continue à l'indice $N/2-2 = 3$: `5`.
* `5 < 8`, échanger `8` et `5` (aka `max(2, 5, 8)`)

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((8));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::

. . .

```
        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
```

# Exemple de tri par tas (3/N)

```
        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
```

::: columns

:::: column

**But:** Transformer l'arbre en tas.

* Indice $N/2-1 = 4$: `12`.
* Déjà un tas, rien à faire.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((5));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((8));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Transformer l'arbre en tas.

* Indice $N/2-2 = 3$: `5`.
* `5 < 8`, `5 <=> max(2, 5, 8)`

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((8));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::

```
                   *                *
        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
```

# Exemple de tri par tas (4/N)

```
        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
```

::: columns

:::: column

**But:** Transformer l'arbre en tas.

* Indice $N/2-3 = 1$: `16`.
* Déjà un tas, rien à faire.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((16));
    id0-->id2((8));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Transformer l'arbre en tas.

* Indice $N/2-4 = 1$: `1`.
* `1 < 16 && 1 < 8`, `1 <=> max(1, 16, 8)`

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((16))-->id1((1));
    id0-->id2((8));
    id1-->id3((12));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::

```
           *   *
        | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
```


# Exemple de tri par tas (5/N)

```
        | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
```

::: columns

:::: column

**But:** Transformer l'arbre en tas.

* Recommencer avec `1`.
* `1 <=> max(1, 12, 7)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((16))-->id1((12));
    id0-->id2((8));
    id1-->id3((1));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((10));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Transformer l'arbre en tas.

* Recommencer avec `1`.
* `1 <=> max(1, 10, 6)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((16))-->id1((12));
    id0-->id2((8));
    id1-->id3((10));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((6));
    id4-->id9((4));
    id4-->id10(( ));    
    style id10 fill:#fff,stroke:#fff
```

::::

:::

```
                *        *               *
        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
```

* L'arbre est un tas.

# Exemple de tri par tas (6/N)

```
        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `16` (`max` de l'arbre) avec `4`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((4))-->id1((12));
    id0-->id2((8));
    id1-->id3((10));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((6));
```

::::

:::: column

**But:** Trier les tas.

* `4 <=> max(4, 12, 8)`.
* `4 <=> max(4, 10, 7)`.
* `4 <=> max(4, 1, 6)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((12))-->id1((10));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((4));
```

::::

:::

```
        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
```


# Exemple de tri par tas (7/N)

```
        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `12` (`max` de l'arbre) avec `4`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((4))-->id1((10));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((7));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((  ));
    style id8 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas.

* `4 <=> max(4, 10, 8)`.
* `4 <=> max(4, 6, 7)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((10))-->id1((7));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((5));
    id3-->id7((1));
    id3-->id8((  ));
    style id8 fill:#fff,stroke:#fff
```

::::

:::

```
        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
```

# Exemple de tri par tas (8/N)

```
        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `10` (`max` de l'arbre) avec `1`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((7));
    id0-->id2((8));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((5));
```

::::

:::: column

**But:** Trier les tas.

* `1 <=> max(1, 7, 8)`.
* `5 <=> max(1, 2, 5)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((8))-->id1((7));
    id0-->id2((5));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((1));
```

::::

:::

```
        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
```

# Exemple de tri par tas (9/N)

```
        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `8` (`max` de l'arbre) avec `1`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((7));
    id0-->id2((5));
    id1-->id3((6));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((  ));
    style id6 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas.

* `1 <=> max(1, 7, 5)`.
* `1 <=> max(1, 6, 4)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((7))-->id1((6));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((4));
    id2-->id5((2));
    id2-->id6((  ));
    style id6 fill:#fff,stroke:#fff
```

::::

:::

```
        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
```

# Exemple de tri par tas (10/N)

```
        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `7` (`max` de l'arbre) avec `2`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((2))-->id1((6));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((4));
```

::::

:::: column

**But:** Trier les tas.

* `2 <=> max(2, 6, 5)`.
* `2 <=> max(2, 1, 4)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((6))-->id1((4));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((2));
```

::::

:::

```
        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
```

# Exemple de tri par tas (11/N)

```
        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `6` (`max` de l'arbre) avec `2`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((2))-->id1((4));
    id0-->id2((5));
    id1-->id3((1));
    id1-->id4((  ));
    style id4 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas.

* `2 <=> max(2, 4, 5)`.
* `2 <=> max(2, 1, 4)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((5))-->id1((4));
    id0-->id2((2));
    id1-->id3((1));
    id1-->id4((  ));
    style id4 fill:#fff,stroke:#fff
```

::::

:::

```
        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
```

# Exemple de tri par tas (12/N)

```
        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `5` (`max` de l'arbre) avec `1`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((1))-->id1((4));
    id0-->id2((2));
```

::::

:::: column

**But:** Trier les tas.

* `1 <=> max(1, 4, 2)`.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((4))-->id1((1));
    id0-->id2((2));
```

::::

:::

```
        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
```

# Exemple de tri par tas (13/N)

```
        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
```

::: columns

:::: column

**But:** Trier les tas.

* Échanger la racine, `4` (`max` de l'arbre) avec `2`.
* Traiter la racine.

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((2))-->id1((1));
    id0-->id2(( ));
    style id2 fill:#fff,stroke:#fff
```

::::

:::: column

**But:** Trier les tas. Plus rien à trier

* On fait les 2 dernières étapes en vitesse.
* Échange `2` avec `1`.
* Il reste que `1`. GGWP!


::::

:::

```
        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
```

# Exercice (10min)

* Trier par tas le tableau

```
        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
```

* Mettez autant de détails que possible.
* Que constatez-vous?
* Postez le résultat sur matrix.


# L'algorithme du tri par tas (1/4)

\footnotesize

## Deux étapes

1. Entassement (tamisage): transformer l'arbre en tas.
2. Échanger la racine avec le dernier élément et entasser la racine.

## Pseudo-code d'entassement de l'arbre (5 min, matrix)

. . .

```
tri_par_tas(tab)
    entassement(tab)
    échanger(tab[0], tab[size(tab)-1])
    pour i = size(tab)-1 à 2 
        promotion(tab, 0)
        échanger(tab[0], tab[i-1])
entassement(tab)
    pour i = size(tab) / 2 - 1 jusqu'à 0
        promotion(tab, i)
promotion(tab, i)
    ind_max = ind_max(tab, i, gauche(i), droite(i))
    si i != ind_max
        échanger(tab[i], tab[ind_max])
        promotion(tab, ind_max)
```

# L'algorithme du tri par tas (2/4)

* Fonctions utilitaires

```
int ind_max(tab, i, g, d)
    ind_max = i
    si tab[ind_max] < tab[l]
        ind_max = l
    si tab[ind_mx] < tab[r]
        ind_max = r
    retourne ind_max
int gauche(i)
    retourne 2 * i + 1
int droite(i)
    retourne 2 * i + 2
```


# L'algorithme du tri par tas (3/4)

\footnotesize

## Implémenter en C l'algorithme du tri par tas (matrix, 20min)

. . .

```C 
void heapsort(int size, int tab[size]) {
    heapify(size, tab);
    swap(tab, tab + size - 1);
    for (int s = size - 1; s > 1; s--) {
        sift_up(s, tab, 0);
        swap(tab, tab + s - 1);
    }
}
void heapify(int size, int tab[size]) {
    for (int i = size / 2 - 1; i >= 0; i--) {
        sift_up(size, tab, i);
    }
}
void sift_up(int size, int tab[size], int i) {
    int ind_max = ind_max3(size, tab, i, left(i), right(i));
    if (i != ind_max) {
        swap(tab + i, tab + ind_max);
        sift_up(size, tab, ind_max);
    }
}
```

# L'algorithme du tri par tas (4/4)

\footnotesize

## Fonctions utilitaires

. . .

```C
int ind_max3(int size, int tab[size], int i, int l, int r) {
    int ind_max = i;
    if (l < size && tab[ind_max] < tab[l]) {
        ind_max = l;
    }
    if (r < size && tab[ind_max] < tab[r]) {
        ind_max = r;
    }
    return ind_max;
}
void swap(int *a, int *b) {
    int tmp = *a;
    *a      = *b;
    *b      = tmp;
}
int left(int i) {
    return 2 * i + 1;
}
int right(int i) {
    return 2 * i + 2;
}
```


# Complexités

::: columns

:::: column

## Complexité de la recherche

1. En moyenne?
2. Dans le pire des cas?

. . .

1. $O(\log_2(N))$
2. $O(N)$

::::

:::: column

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((10))-->id1((9));
    id0-->id8((  ));
    id1-->id2((7));
    id1-->id9((  ));
    id2-->id3((6));
    id2-->id10((  ));
    id3-->id4((5));
    id3-->id11((  ));
    style id8 fill:#fff,stroke:#fff
    style id9 fill:#fff,stroke:#fff
    style id10 fill:#fff,stroke:#fff
    style id11 fill:#fff,stroke:#fff
```

::::

:::

# Un meilleur arbre

* Quelle propriété doit satisfaire un arbre pour être $O(\log_2(N))$?

. . .

* Si on a environ le même nombre de noeuds dans les sous-arbres.

## Définition

Un arbre binaire est parfaitement équilibré si, pour chaque
nœud, la différence entre les nombres de nœuds des sous-
arbres gauche et droit vaut au plus 1.

* Si l'arbre est **parfaitement équilibré**, alors tout ira bien.
* Quelle est la hauteur (profondeur) d'un arbre parfaitement équilibré?

. . .

* $O(\log_2(N))$.


# Équilibre parfait ou pas?

::: columns

:::: column

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((W))-->id1((B));
    id0-->id8((Y));
    id1-->id2((A));
    id1-->id9((  ));
    id8-->id10((X));
    id8-->id11((  ));
    style id9 fill:#fff,stroke:#fff
    style id11 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

```
É
Q
U
I
L
I
B
R
É
```

::::

:::

# Équilibre parfait ou pas?

::: columns

:::: column

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((16))-->id1((10));
    id0-->id2((19));
    id1-->id3((8));
    id1-->id4((12));
    id4-->id5((11));
    id4-->id6((  ));
    id2-->id7((17));
    id2-->id8((  ));
    id7-->id9((  ));
    id7-->id10((18));
    style id6 fill:#fff,stroke:#fff
    style id8 fill:#fff,stroke:#fff
    style id9 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

```
P 
A
S 

É
Q
U
I
L
I
B
R
É
```

::::

:::

# Arbres AVL

* Quand est-ce qu'on équilibre un arbre?

. . .

* A l'insertion/suppression.
* Maintenir un arbre en état d'équilibre parfait: cher (insertion, suppression).
* On peut "relaxer" la condition d'équilibre: profondeur (hauteur) au lieu du
  nombre de neouds:
    * La hauteur $\sim\log_2(N)$.

## Définition

Un arbre AVL (Adelson-Velskii et Landis) est un arbre binaire de recherche dans
lequel, pour chaque nœud, la différence de hauteur entre le sous-arbre gauche et droit vaut au plus 1.

* Relation entre noeuds et hauteur:
$$
\log_2(1+N)\leq 1+H\leq 1.44\cdot\log_2(2+N),\quad N=10^5,\ 17\leq H \leq 25.
$$
* Permet l'équilibrage en temps constant: insertion/suppression $O(\log_2(N))$.

# Notation

* `hg`: hauteur du sous-arbre gauche.
* `hd`: hauteur du sous-arbre droit.
* `facteur d'équilibre = fe = hd - hg`
* Que vaut `fe` si l'arbre est AVL?

. . .

* `fe = {-1, 0, 1}`


# AVL ou pas?

::: columns

:::: column

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((12))-->id1((10));
    id0-->id2((19));
    id2-->id3((17));
    id2-->id4((97));
```

::::

:::: column

. . .

```
A
V
L
```

::::

:::

# AVL ou pas?

::: columns

:::: column

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((12))-->id1((1));
    id0-->id2((19));
    id2-->id3((17));
    id2-->id4((97));
    id4-->id5((37));
    id4-->id6((  ));
    style id6 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

```
P
A
S

A
V
L
```

::::

:::
+736 −0

File added.

Preview size limit exceeded, changes collapsed.

+387 −0
Original line number Diff line number Diff line
---
title: "Arbres AVL et quadtrees"
date: "2022-03-23"
patat:
  eval:
    tai:
      command: fish
      fragment: false
      replace: true
    ccc:
      command: fish
      fragment: false
      replace: true
  images:
    backend: auto
---

# Questions sur les notions du dernier cours

## Quel est l'algorithme d'insertion dans un arbre AVL?

. . .

* Insertion comme dans un arbre binaire de recherche.
* Rééquilibrage si le facteur d'équilibre est de -2 ou +2.

## Quelles sont les briques élémentaires du rééquilibrage?

. . .

* La rotation gauche ou droite.

# Encore un petit exercice

* Insérer les nœuds suivants dans un arbre AVL

```
25 | 60 | 35 | 10 | 5 | 20 | 65 | 45 | 70 | 40 | 50 | 55 | 30 | 15
```

## Un à un et le/la premier/ère qui poste la bonne réponse sur matrix a un point

# Suppression dans un arbre AVL


::: columns

:::: column

## Algorithme par problème: supprimer 10

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((8))-->id1((4));
    id0-->id2((10));
    id1-->id3((2));
    id1-->id4((6));
    id3-->id5((1));
    id3-->id6((  ))
    id4-->id7((  ))
    id4-->id8((7))
    id2-->id9((9))
    id2-->id10((14))
    id10-->id11((12))
    id10-->id12((16))
    style id6 fill:#fff,stroke:#fff
    style id7 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

## Algorithme par problème: supprimer 10

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((8))-->id1((4));
    id0-->id2((12));
    id1-->id3((2));
    id1-->id4((6));
    id3-->id5((1));
    id3-->id6((  ))
    id4-->id7((  ))
    id4-->id8((7))
    id2-->id9((9))
    id2-->id10((14))
    id10-->id11((  ))
    id10-->id12((16))
    style id6 fill:#fff,stroke:#fff
    style id7 fill:#fff,stroke:#fff
    style id11 fill:#fff,stroke:#fff
```

::::

:::

# Suppression dans un arbre AVL


::: columns

:::: column

## Algorithme par problème: supprimer 8

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((8))-->id1((4));
    id0-->id2((12));
    id1-->id3((2));
    id1-->id4((6));
    id3-->id5((1));
    id3-->id6((  ))
    id4-->id7((  ))
    id4-->id8((7))
    id2-->id9((9))
    id2-->id10((14))
    id10-->id11((  ))
    id10-->id12((16))
    style id6 fill:#fff,stroke:#fff
    style id7 fill:#fff,stroke:#fff
    style id11 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

## Algorithme par problème: rotation de 12

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((9))-->id1((4));
    id0-->id2((12));
    id1-->id3((2));
    id1-->id4((6));
    id3-->id5((1));
    id3-->id6((  ))
    id4-->id7((  ))
    id4-->id8((7))
    id2-->id9((  ))
    id2-->id10((14))
    id10-->id11((  ))
    id10-->id12((16))
    style id6 fill:#fff,stroke:#fff
    style id7 fill:#fff,stroke:#fff
    style id9 fill:#fff,stroke:#fff
    style id11 fill:#fff,stroke:#fff
```

::::

:::

# Suppression dans un arbre AVL

::: columns

:::: column

## Algorithme par problème: rotation de 12

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((9))-->id1((4));
    id0-->id2((14));
    id1-->id3((2));
    id1-->id4((6));
    id3-->id5((1));
    id3-->id6((  ))
    id4-->id7((  ))
    id4-->id8((7))
    id2-->id9((12))
    id2-->id10((16))
    style id6 fill:#fff,stroke:#fff
    style id7 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

1. On supprime comme d'habitude.
2. On rééquilibre si besoin à l'endroit de la suppression.

* Facile non?

. . .

* Plus dur....

::::

:::

# Suppression dans un arbre AVL 2.0

::: columns

:::: column

## Algorithme par problème: suppression de 30

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((50))-->id1((30));
    id0-->id2((100));
    id1-->id3((10));
    id1-->id4((40));
    id3-->id5((  ));
    id3-->id6((20))
    id2-->id7((80))
    id2-->id8((200))
    id7-->id9((70))
    id7-->id10((90))
    id9-->id11((60))
    id9-->id12((  ))
    id8-->id13((  ))
    id8-->id14((300))
    style id5 fill:#fff,stroke:#fff
    style id12 fill:#fff,stroke:#fff
    style id13 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

## Algorithme par problème: rotation GD autour de 40

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((50))-->id1((40));
    id0-->id2((100));
    id1-->id3((10));
    id1-->id4((  ));
    id3-->id5((  ));
    id3-->id6((20))
    id2-->id7((80))
    id2-->id8((200))
    id7-->id9((70))
    id7-->id10((90))
    id9-->id11((60))
    id9-->id12((  ))
    id8-->id13((  ))
    id8-->id14((300))
    style id4 fill:#fff,stroke:#fff
    style id5 fill:#fff,stroke:#fff
    style id12 fill:#fff,stroke:#fff
    style id13 fill:#fff,stroke:#fff
```

::::

:::

# Suppression dans un arbre AVL 2.0

::: columns

:::: column

## Argl! 50 est déséquilibré!

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((50))-->id1((20));
    id0-->id2((100));
    id1-->id3((10));
    id1-->id4((40));
    id2-->id7((80))
    id2-->id8((200))
    id7-->id9((70))
    id7-->id10((90))
    id9-->id11((60))
    id9-->id12((  ))
    id8-->id13((  ))
    id8-->id14((300))
    style id12 fill:#fff,stroke:#fff
    style id13 fill:#fff,stroke:#fff
```

::::

:::: column

. . .

## Algorithme par problème: rotation DG autour de 50

```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
    id0((80))-->id1((50));
    id0-->id2((100));
    id1-->id3((20));
    id1-->id4((70));
    id3-->id5((10));
    id3-->id6((40));
    id4-->id9((60))
    id4-->id10((  ))
    id2-->id7((90))
    id2-->id8((200))
    id8-->id13((  ))
    id8-->id14((300))
    style id10 fill:#fff,stroke:#fff
    style id13 fill:#fff,stroke:#fff
```

::::

:::

# Résumé de la suppression

1. On supprime comme pour un arbre binaire de recherche.
2. Si un nœud est déséquilibré, on le rééquilibre.
    * Cette opération pour déséquilibrer un autre nœud.
3. On continue à rééquilibrer tant qu'il y a des nœuds à équilibrer.

# Les arbres quaternaires

## Définition

Arbre dont chaque nœud a 4 enfants ou aucun. 

![Un exemple de quadtree.](figs/quad_ex.svg)

# Les arbres quaternaires

## Cas d'utilisation

Typiquement utilisés pour représenter des données bidimensionnelles.

Son équivalent tri-dimensionnel est l'octree (chaque nœud a 8 enfants ou aucun).

## Cas d'utilisation: images

* Stockage: compression.
* Transformations: symétries, rotations, etc.

## Cas d'utilisation: simulation

* Indexation spatiale.
* Détection de collisions.
* Simulation de galaxies, Barnes-Hut.

# Exemple de compression

::: columns

:::: {.column width=30%}

## Comment représenter l'image

![Image noir/blanc.](figs/board_blacked_parts.svg)

::::

:::: {.column width=70%}

## Sous la forme d'un arbre quaternaire?

. . .

![L'arbre quaternaire correspondant.](figs/quad_img.svg)

**Économie?**

. . .

Image 64 pixels, arbre 25 neouds.

::::

:::

slides_2021/cours_2.md

0 → 100644
+374 −0

File added.

Preview size limit exceeded, changes collapsed.

+721 −0

File added.

Preview size limit exceeded, changes collapsed.

+830 −0

File added.

Preview size limit exceeded, changes collapsed.

+602 −0

File added.

Preview size limit exceeded, changes collapsed.

+445 −0

File added.

Preview size limit exceeded, changes collapsed.

+883 −0

File added.

Preview size limit exceeded, changes collapsed.

+579 −0

File added.

Preview size limit exceeded, changes collapsed.

+776 −0

File added.

Preview size limit exceeded, changes collapsed.

+681 −0

File added.

Preview size limit exceeded, changes collapsed.

+14 −0
Original line number Diff line number Diff line
version: "3.3"
services:
    slides:
        #To use dockerfile : build: . 
        image:  omalaspinas/pandoc:latest
        environment:
            USER: 1000
            GROUP: 1000
        container_name: slides
        volumes:
            - ./:/data
        # entrypoint: ["make", "all"]
        working_dir: /data
        # user: "$(id -u):$(id -g)"