Как динамичен 2D масив се съхранява в паметта?

Как се съхранява 2D масив в паметта?

Мислех за следния подход, при който редовете се съхраняват като непрекъснати блокове памет.

|_________||___< em>______|______ __|________|.. .|_________|

Достъпът до елементите се извършва като (i,j) -> n*i+j, където n е размерът на матрицата (ако приемем, че е nxn).

Но какво ще стане, ако искам да добавя нова колона към него? Ще трябва да актуализирам всеки (n+1)-ти елемент във всеки ред и също да ги преместя надясно, но това е твърде скъпо от изчислителна гледна точка.

Друг вариант би бил да копирате матрицата на ново място и да актуализирате редовете с елементите на новата колона в движение. Но това също не е твърде ефективно, ако масивът е голям.

И накрая третата опция, за която се сетих, е да разпределя фиксирано количество памет за всеки ред и когато добавя нова колона, не трябва да премествам редовете надясно.

Не мога да имам пропуски в паметта, така че всички блокове трябва да са последователни.

Не искам реализация на C, използваща указатели и действителната RAM памет, просто съм любопитен за теоретичен подход за съхраняване на динамичен 2d масив в паметта, така че да е лесно да се добавят нови редове или колони към него .

Има ли други по-ефективни подходи?


person flowerpower    schedule 04.01.2012    source източник
comment
С какви размери работите? говорим ли за 10 елемента от 1 000 000 елемента?   -  person Martin Kristiansen    schedule 05.01.2012


Отговори (2)


Ако знаете, че създавате 2D масив, който ще разширите, един подход би бил да разпределите повече размер, отколкото ви е необходим за всяко измерение. Проследявайте действителния и разпределения размер и когато действителният размер надвишава разпределения, направете следното:

  • удвоете размера на разпределението
  • копирайте всички данни от стария масив в новия
  • освободи стария масив

Това би било 2D разширение на обща техника за разпределяне на динамични 1D масиви.

person Greg Hewgill    schedule 04.01.2012
comment
Добра идея, но се чудя дали нарушава изискването му паметта да бъде непрекъсната. - person Jim Clay; 05.01.2012
comment
Това изискване беше добавено след поставянето на първоначалния въпрос. Не знам дали блокът означава конкретен ред или цялата структура от данни. - person Greg Hewgill; 05.01.2012
comment
С това имах предвид, че не мога да имам пропуски в паметта. Да предположим, че искам да го съхраня в двоичен файл, мисля, че това ще пасне на моя сценарий за памет. - person flowerpower; 05.01.2012
comment
В този случай имате няколко възможности за избор: (1) съхранявайте паметта в един непрекъснат блок, което означава, че трябва да пренаредите всичко, когато добавяте нова колона; (2) използвайте оформление за съхранение, както предлагам, но записвайте само активните елементи от данни в двоичния файл; (3) позволете празнини във вашия двоичен файл (ще ви трябва заглавка в него, за да опишете в каква форма са следните данни). - person Greg Hewgill; 05.01.2012

Ако имате нужда масивите да се разширяват и да бъдат съседни в паметта, един от начините да постигнете това е просто да използвате 1d масив и да „фалшифицирате“ 2-рото измерение.

Ако вашият първоначален 1d масив има повече място, отколкото изискват всички ваши 2d масиви, това няма да изисква преместване в паметта (потенциално избягване на пропуски). Въпреки това, в зависимост от това как го прилагате, вмъкване, което кара един от подмасивите да расте, може да изисква разместване на по-късни елементи надолу (можете също да имате празнини във вашия масив, но вярвам, че това нарушава вашето изискване за липса на пропуски).

Ако наистина имате нужда от 2 измерения, тогава отговорът на greg е правилният начин. Ако знаете размера на вашите данни като начало, това го прави много по-лесно.

person cjh    schedule 04.01.2012