Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab_pr_ta / Лаб_та_пр__10.doc
Скачиваний:
31
Добавлен:
07.02.2016
Размер:
166.91 Кб
Скачать

Стисле та індексне зберігання лінійних списків.

Нехай у списку B=<k1, k2, ..., kn> кілька елементів мають однакове значення v; список будується з В заміною кожного елемента ki парою k1’ =(i, ki), а список з В’ викресл.юванням усіх пар k1’ =(i, v). Стислим зберіганням В є будь - який метод Зберігання В’’, в якому не записуються елементи з значенням v. Цінність стислого зберігання списку при значній кількості елементів, рівних v, полягаї в можливості зменшення пам'яті для його зберігання.

Пошук і-того елементу списку при зв'язаному стислому зберіганні здійснюється методом повного перегляду, а при послідовному стислому зберіганні - методом бінарного пошуку. Переваги та недоліки послідовного і зв'язаного стислих зберігань аналогічні перевагам та недолікам послідовного і зв'язаного зберігань.

Приклад. На вході (файл stdin) задані дві послідовності цілих чисел

М={m1,m2,...,m10000},

N={n1,n2,...,n10000}.

Відомо, що не менше 92% елементів послідовності М рівно нулю. Скласти програму для обчислення скалярного добутку векторўв М і N

Організуємо для списку М послідовне стисле зберігання в масиві структур М. Програмою розв'язання задачў буде:

/*scalprod-скалярний добуток векторўв*/

main ()

{

int i,inp,sum;

struct {int nm, val;}M[800],*p;

p=M;

for (i=0;i<10000;i++)

{

scanf("%d",&inp);

if (p->val=inp) (p++)->nm=i;

}

p->nm=10000; sum=0; p=M;

for (i=0;i<10000;i++)

{

scanf("%d",&inp);

if(i==p->nm)sum+=(p++)->val*inp;

}

printf("sum=%d\n",sum);

}

Індексне зберігання. Спосіб індексного зберігання інформації полягає в тім, що початковий список В=(к12,...кn) ділиться на кількість підсписків В12,...Вm так, що кожний елемент списку В

потрапляє тільки в один з підсписків; додатково використовується індексний список з m елементами, що показують на початки списків В12,...,Вm .Таке зберігання списку називається індексним з підсписками В12,...,Вm та індексним списком Х=<adg1, adg2,...,adgm>, де adgj - адреса початку підсписку Вj,1<=j<=m. За індексного зберігання елемента к, що належить підсписку Вi, має індекс і.

Для індексного зберігання початковий список В часто перетворюють у список В', вміщуючи в кожен вузол його порядковий номер в В. Вj-й елемент індексного списку Х, крім adgі, може вводитися додаткова інформація про підсписок Вj. Поділ списку В на підсписки здійснюється так, щоб усі його елементи з певною властивістю pj потрапили в один підсписок Вj. Цінність індексного зберігання в тому, що для пошуку елемента к із заданою властивістю рj досить переглянути тільки елементи підсписку Вj; його почоток перебуває в індексному списку Х, оскільки для будь-якого к є Ві при і<>j властивість рj не виконуїться.

Для поділу списку В використовується індексна функція g(k),яка виробляє за елементом к його індекс, тобто g(k)=j. Функція g звичайно залежить від позиції к в В або від значення певного його компонента - ключа елемента к.

Приклад. Розглянемо список В=<к12,...,к9> з елементами к1=(17,У), к2=(23,Н), к3=(60,І), к4=(90,S), к5=(166,Т), к6=(177,Т), к7=(250,U), k8=(288,W), k9=(300,S).

Якщо для поділу цього списку на підсписки візьмемо індксну функцію ga(k)==1+(поз.к-1)/3, де поз. к - порядковий номер елемента к в початковому списку В, то список розділиться на підсписки:

B1=[(17,Y), (23,H), (60,I)]

B2=[(90,S), (166,T), (177,T)]

B3=[(250,U), (288,W), (300,S)]

Додаючи кожен вузол ще порядковий номер (поз.) елемента в початковому списку, дістанемо:

B'1=[(1,17,Y), (2,23,H), (3,60,I)],

B'2=[(4,90,S), (5,166,T), (6,177,T)],

B'3=[(7,250,U), (8,288,W), (9,300,S)].

За індексною функцією gb(k)=1+(поз.k-1)% 3 буде:

B"1=[(1,17,Y), (4,90,S), (7,250,U)],

B"2=[(2,23,H), (5,166,T), (8,288,W)],

B"3=[(3,60,I), (6,177,T), (9,300,S)].

Тепер для визначення, наприклад, вузла к6 достатньо пернглянути тільки один список: В'2 для першого поділу, бо ga(6)=2, або В'3 для другого подўлу, бо gb(6)=3. Якщо за функцію поділу взяти gс(к)=1+ /100, де -перший компонент (ключ.) елемента к. то

B1=[(17,Y), (23,H), (60,I), (90,S)],

B2=[(166,T), (177,T)],

B3=[(250,U),(288,W)],

B4=[(300,S)].

Відшукуючи вузол к з ключем =177, досить переглянути список В2, бо gc(177)=2.

Реалізація індексного зберігання. Оскільки довжина списку індексів Х відома, то часто використовують послідовно-зв'язане індексне зберігання: Х - послідовно, забезпечуючи прямий доступ до його елементів; В1, В2,...,Вm - зв'язано, що спрощуї додавання та вилучення елементів.

Приклад. На вході (файл stdin) задана послідовність цілих додатніх чисел, не більших 9999, що закінчується нулем. Написати функцію для введення цієї послідовності та організації її послідовно - зв'язаного індексного зберігання так, щоб числа, які мають однакові дві останні цифри, були в одному підсписку.

За індексну функцію візьмемо g(k)=k% 100, а для індексного списку Х- масив з 100 елементів. Щоб в підсписках елементи розміщувались у порядку початкової послідовності, підсписки організуються, як циклічні списки, а після закінчення введення послідовності циклічні списки перетворюються у звичайні. Функція indtx розв'язуї задачу так:

/* index - формування індексного зберігання* /

index(X)

LISTP X[100];

{

LISTP new ( ),t; int inp` t;

for (i=0; i<100; i++) X[i]=NULL;

while(scanf ("%d",& inp)==1 && inp!=0)

if (X[i=inp%100]

{

X[i]-> next=new [inp,X[i]->next);

X[i]=X[i]->next;

}

else{X[i]=new(inp, NULL);

X[i]->next=X[i];}

for(i=0;i>100;i++)

if(t=X[i])

{

X[i]=t->next; t->next=NULL;

}

}

Соседние файлы в папке lab_pr_ta