// 9. hét – A dinamikus memóriakezelés egyszerű modellje: a memória egy rekordtömb, a mutató egy index.
// Futtatás: go run ./h09/memorymodel
package main

import "fmt"

const (
	Nil  = -1
	Size = 8
)

type Elem struct {
	Value string
	Next  int
}

var (
	mem  [Size]Elem
	free int // a szabad lista feje
)

func initMemory() {
	for i := 0; i < Size-1; i++ {
		mem[i].Next = i + 1
	}
	mem[Size-1].Next = Nil
	free = 0
}

// allocate (Lefoglal): hely a szabad lista elejéről; Nil, ha nincs.
func allocate() int {
	if free == Nil {
		return Nil
	}
	p := free
	free = mem[p].Next
	return p
}

// release (Felszabadít): vissza a szabad lista elejére.
func release(p int) {
	mem[p] = Elem{Next: free}
	free = p
}

func printMemory(head int) {
	fmt.Println("  index | érték | köv")
	for i, e := range mem {
		next := fmt.Sprint(e.Next)
		if e.Next == Nil {
			next = "Nil"
		}
		fmt.Printf("  %5d | %5s | %3s\n", i, e.Value, next)
	}
	fmt.Print("  lista: ")
	for p := head; p != Nil; p = mem[p].Next {
		fmt.Printf("%s(%d) ", mem[p].Value, p)
	}
	fmt.Print("\n  szabad: ")
	for p := free; p != Nil; p = mem[p].Next {
		fmt.Print(p, " ")
	}
	fmt.Println()
}

func main() {
	initMemory()
	head := Nil
	for _, s := range []string{"D", "C", "B", "A"} { // beszúrás az elejére
		p := allocate()
		mem[p].Value = s
		mem[p].Next = head
		head = p
	}
	fmt.Println("4 beszúrás után:")
	printMemory(head)

	p := head // A törlése az elejéről
	head = mem[p].Next
	release(p)
	q := head // C törlése B mögül
	p = mem[q].Next
	mem[q].Next = mem[p].Next
	release(p)
	fmt.Println("\nA és C törlése után:")
	printMemory(head)
}
