Společnost Proton AG stojící za Proton Mailem a dalšími službami přidala do svého portfolia online tabulky Proton Sheets v Proton Drive.
O víkendu (15:00 až 23:00) probíha EmacsConf 2025, tj. online konference vývojářů a uživatelů editoru GNU Emacs. Sledovat ji lze na stránkách konference. Záznamy budou k dispozici přímo z programu.
Provozovatel internetové encyklopedie Wikipedia jedná s velkými technologickými firmami o uzavření dohod podobných té, kterou má s Googlem. Snaží se tak zpeněžit rostoucí závislost firem zabývajících se umělou inteligencí (AI) na svém obsahu. Firmy využívají volně dostupná data z Wikipedie k trénování jazykových modelů, což zvyšuje náklady, které musí nezisková organizace provozující Wikipedii sama nést. Automatické programy
… více »Evropská komise obvinila síť 𝕏 z porušení unijních pravidel, konkrétně nařízení Evropské unie o digitálních službách (DSA). Vyměřila jí za to pokutu 120 milionů eur (2,9 miliardy Kč). Pokuta je podle názoru amerického ministra zahraničí útokem zahraničních vlád na americký lid. K pokutě se vyjádřil i americký viceprezident: „EU by měla podporovat svobodu projevu, a ne útočit na americké společnosti kvůli nesmyslům“.
Společnost Jolla spustila kampaň na podporu svého nového telefonu Jolla Phone se Sailfish OS. Dodání je plánováno na první polovinu příštího roku. Pokud bude alespoň 2 000 zájemců. Záloha na telefon je 99 €. Cena telefonu v rámci kampaně je 499 €.
Netflix kupuje Warner Bros. včetně jejích filmových a televizních studií HBO Max a HBO. Za 72 miliard dolarů (asi 1,5 bilionu korun).
V Las Vegas dnes končí pětidenní konference AWS re:Invent 2025. Společnost Amazon Web Services (AWS) na ní představila celou řadu novinek. Vypíchnout lze 192jádrový CPU Graviton5 nebo AI chip Trainium3.
Firma Proxmox vydala novou serverovou distribuci Datacenter Manager ve verzi 1.0 (poznámky k vydání). Podobně jako Virtual Environment, Mail Gateway či Backup Server je založená na Debianu, k němuž přidává integraci ZFS, webové administrační rozhraní a další. Datacenter Manager je určený ke správě instalací právě ostatních distribucí Proxmox.
Byla vydána nová verze 2.4.66 svobodného multiplatformního webového serveru Apache (httpd). Řešeno je mimo jiné 5 bezpečnostních chyb.
Programovací jazyk JavaScript (Wikipedie) dnes slaví 30 let od svého oficiálního představení 4. prosince 1995.
IMHO se ty operace dají udělat i s jednosměrně zřetězeným seznamem v konstantním čase, jenom to neni zrovna obvyklé řešení (to s "přesměrovánim" ukazatelů).
Operaci vyjmout prvek lze totiž udělat i tak, že si zapamatuješ "obsah" prvku a ten nahradíš "obsahem" jeho následníka (včetně ukazatele na následující prvek).
tak by to šlo.
, protože tam mám ukazatele na ty prvky, takže je stačí jenom prohodit a nemusím nic kopírovat. Takže dík.
2) Nepůjde smazat poslední prvek. I kdyby typ datové položky měl nějakou speciální "prázdnou" hodnotu, nebude jak správně aktualizovat ukazatel na konec seznamu, který je potřeba pro jiné operace.
Místo ukazatele na poslední prvek seznamu můžeš udržovat ukazatel na předposlední prvek.
.
?! Ukazatel na předposlední prvek si právě budeš pamatovat. A jestli si myslel "poslední" místo "předposlední", tak k tomu se z předposledního lehce dostaneš v konstantnim čase...
Máš pravdu, teorie s předposlednim prvkem je blbost. Nicméně by to mělo jít udělat přes "fixní" poslední prvek seznamu. Tzn. poslední prvek seznamu by byl "speciální" prvek, který by se nikdy nemazal.
Myslim to tak, že ten poslední prvek nebude navenek součástí seznamu. Seznam prostě pro N "uživatelskejch" prvků bude mít interně N + 1 prvků.
.
insertAfter(SHandle *, SItem), makeEmpty, moveAfter(SHandle *,SHandle *), moveToFront(SHandle *), moveToBack(SHandle *), remove(SHandle *). U těchto metod totiž potřebujeme vědět předchůdce objektu (prvku)Předpokládám, že předchůdce je právě ten první parametr. Čili hledat ho nepotřebuješ:
insertAfter(SHandle *item, SItem) {item->next = /*novej prvek*/;}moveToFront je jednoduché.remove konstatně moc nejde, leda že bys hodnotu následujícího překopíroval do toho k odebrání, napojil ten následující za následujícím a uvolnil následující.moveToBack a moveAfter imho konstatně nepůjdou.makeEmpty nevím co znamená, ale jestli to zahrnuje uvolňování paměti všech, konstatní složitost to určitě mít nebude...
moveToFront vlastně jednoduché není, ledaže bys zase přehazoval hodnoty, což by se týkalo všech move* a pak by to bylo konstatní.
že se ten další prvek nakopíruje na místo prvku, který chci přesunout.Jj, tak jsem to myslel. Dalo by se to udělat tak, že bys ty hodnoty do toho seznamu nevkládal přímo, ale přes pointer - "kopírování" by pak bylo jednoduchý. Ono s nějakým nasazením třeba templatů nebo něčeho by to v podstatě takhle dopadlo tak jako tak...
takže jsem to měl už připravené jenom jsem to upravil
.
Taky to jde, když pro seznam použiješ jeden "buffer" (kterej budeš třeba exponenciálně zvětšovat) a nebudeš alokovat paměť pro každý prvek zvlášť.
Správnou odpověď ti dá asi jenom zadavatel, tedy cvičící. Já bych to tipoval, že operace smazat seznam konstantní bejt nemusí, jenom to neni v zadání explicitně napsaný. V nejhoršim případě můžeš prostě jenom "vynulovat" ukazatel na začátek seznamu a argumentovat tim, že o uvolňování paměti se v zadání nic nepíše
.
.
a nebo si ten Garbage collector můžeš implementovat sám. Udělat ještě jeden seznam prvky alokované, ale jinak úplně na h*vn*, v případě že budeš chtít alokovat, tak můžeš mrknout do toho druhého seznamu a prvky už alokované jen znova přidělíš a ještě si do toho napíšeš nějakou čistící rutinu, která po nějaké časové periodě mrkne do toho druhého seznamu a pokud v něm bude nějaký prvek, tak ho podle pointerů projede a celý uvolní. U procedur z vnějšího rozhraní dodržíš zadání a jak se to dělá uvnitř už nikoho nemusí zajímat.
Ale to makeEmpty konstantně nejdeJde, ale ne standardní alokaci paměti. Je třeba použít jiný typ alokace, tj. buď si jí dělat osobně (např. přes
mmap()), nebo použít nějaký hiearchický alokator, jako třeba obstack nebo talloc. Když pak chcete zahodit celý seznam, tak stačí jen zrušit kontajner, ve kterém jsou jednolivé objekty alokovány.
mmap() má konstantní časovou složitost, což (1) Vám nikdo neslibuje, (2) není pravda.
mmap()uje /dev/zero, což je metoda, jakou používají používají i standardní knihovny (vedle brk()/sbrk()). Za optimálních podmínek je odmapování otázka jediného volání jádra, takže v praxi nemá uživatelský program stejně žádnou rychlejší metodu, jak navrátit paměť operačnímu systému.
V moderních OS je dokonce možné ještě dále snížit režii jádra použitím stránek větších než 4KB (běžně 1MB, u nejnovějších procesorů až 1GB), což má i kladný vliv na rychlost přístupu k této paměti (lepší využitím TBL cache). V ultimativním případě se dá celá komplikovaná struktura uvolnit v čase velmi blízkém O(1), tedy pokud se do takovéto olbřímí stránky vejde celá.
Bohužel opravdu konstantí časová složitost opravdu zajistit nejde, ale dá se jí dost přiblížit zamknutím stránek v paměti a naplánování se jako realtime proces. Jenže pravé realtimové procesy stejně většinou nepoužívají klasickou dynamickou alokaci, buď mají všechny struktury statické, nebo přidělují bloky pevné velikosti.
mmap() zdaleka nezávisí jenom na stránkách, ale (zrovna v případě Linuxu, jiné systémy na tom jsou podobně) i na režii VMA-listů, které mají logaritmickou složitost vzhledem k počtu prvků – jsou to ve skutečnosti vyhledávací stromy, protože je potřeba umět pro nový blok paměti najít volné místo v adresním prostoru. Zamykání stránek od toho nepomůže.
Implementujte třídy SHandle, SItem a SList, reprezentující prvky jednosměrně zřetězeného seznamu. SList - samotný spojový seznam, SHandle - ukazatel na SItem, SItem - prvek seznamu Implementujte operace pro SList head(), first(), last(), isEmpty(), popFront(), pushFront(SItem), pushBack(SItem), insertAfter(SHandle *, SItem), concat(SList *), makeEmpty,moveAfter(SHandle *,SHandle *), moveToFront(SHandle *), moveToBack(SHandle *), remove(SHandle *) s konstantní složitostí a findNext(SItem *, SHandle *) se složitostí O(n).
found=false;
for (c=str;*c; c++)
if (*c=='a')
{
found=true;
}
for (c=str;*c;c++)
if (*c=='a')
{
found=true;
break;
}
printf("found %d\n",found);
if next == end free (end); end = this; end;to ti zaruci, ze spojak stale ukazuje spravne.
def remove (link)
if link.next == List.last
data = link.data
List.last = link
else
#normalni remove
end
return data
end
To přece není až tak složité. Trik je v rozdílu mezi SHandle a SItem.
SHandle je datová struktura pro uživatele transparentní; je to nějaký pointer do seznamu, s nímž uživatel nebude nic provádět, jen ho může podstrčit tomu API. (Tedy obdoba C++ iterátoru.) Takové věci se většinou ve veřejných headerech nechávají jako incomplete type, aby se je nikdo nesnažil nějak „instanciovat“ nebo kopírovat. (Ale to není podstatné.)
No a když mám přímo pointer na prvek toho seznamu, je implementace insertAfter(SHandle *, SItem) v O(1) triviální.
Pro jednoduchost (a odstranění zbytečných ifů) je dobré mít v seznamu vždy alespoň jeden prvek, tedy jakousi hlavu, která v případě prázdného seznamu bude ukazovat sama na sebe. Implementaci to výrazně zjednoduší. A co je ještě důležitější — umožní to navíc implementaci insertBefore(SHandle *, SItem) v O(1). Struktura SHandle jednoduše nebude ukazovat přímo na referencovaný prvek seznamu, ale na jeho předchůdce. Implementace insertBefore() i insertAfter() v O(1) je pak snadná.
Ještě jednou základní pointa:
insertAfter(SItem where, SItem newItem) lze u seznamu provést pouze v O(n).insertAfter(SHandle * where, SItem newItem) lze provést v O(1).insertBefore() platí totéž.Zapomněl jsem to explicitně napsat, ale požadované moveAfter(), moveBefore(), moveToBack() či moveToFront() se vyřeší obdobným způsobem. Když potřebuješ znát předchůce, ukazuj prostě pomocí SHandle * na předchůce a ne přímo na referencovaný prvek.
Tiskni
Sdílej: