9. Въведение в структури от данни I

  Свързани списъци.
* В линейната структура свързан списък всяка стойност се съхранява в отделен блок от паметта, заедно с местоположението на съседните блокове в редицата.
* Този начин на съхранение позволява лесно да се вмъкне или отстрани елемент, без да се местят другите елементи - сложност O(1).
* Векторът (или масивът) е също линейна структура, но при вмъкване и изтриване на елемент се местят друти елементи - сложност O(n).
* Във всеки елемент на свързания списък се съхранява една данна и две връзки - съм следващия елемент от списъка и към предишнея елемент от списъка.  

* Вмъкването и изтриването на елемент от свързания списък става лесно - променят се стойностите на няколко връзки.



* Изтриването на елемент от свързан списък не изисква преместване на елементи на списъка.


* За разлика от линейната структура вектора, където има пряк достъп до елементите на вектора (с операция индекс), свързаният списък не осигурява пряк достъп (не поддържа операция индекс).

* В стандартната библиотека шаблони (STL) на С++ има реализация на линейната структура свързан списък - шаблонът list

// list1.cpp
#include <iostream>
#include <string>
#include <list>
using namespace std;

int main()
{  list<string> staff;     /* шаблон за списък */

   staff.push_back("Cracker, Carl");
   staff.push_back("Hacker, Harry");
   staff.push_back("Lam, Larry");
   staff.push_back("Sandman, Susan");

   list<string>::iterator pos;         /* итератор на списък */

/* добавя елемент на четвърто място */
   pos = staff.begin();
   pos++;
   pos++;
   pos++;
   staff.insert(pos, "Reindeer, Rudolf");

/* отстранява втория елемент */
   pos = staff.begin();
   pos++;
   staff.erase(pos);

/* добавя елемент на последно място */
   pos = staff.end();
   staff.insert(pos, "Zeider, Zeev");

/* обхождане на списък */
   for (pos = staff.begin(); pos != staff.end(); pos++)
      cout << *pos << "\n";      /* извежда съдържание на текущата позиция */
   return 0;
}

Cracker, Carl
Lam, Larry
Reindeer, Rudolf
Sandman, Susan
Zeider, Zeev
Стек и опашка
* Стек е линейна структура от данни с добавяне и изтриване на елементи само от единия край, наречен връх на стека.
* Нарича се още LIFO от last in, first out.
* Две са основните операции: добавяне на елемент към стека - push и изваждане на елемент от стека -  pop.
* Реализация в STL.
stack<string> s;
s.push("Tom");
s.push("Dick");
s.push("Harry");
while (s.size() > 0)
{ cout << s.top() << "\n";
s.pop()
}
* Опашка е линейна структура от данни с добавяне на елементи от единия край и изтриване на елементи от другия край.
* Нарича се още FIFO от first in, first out.
* Две са основните операции: добавяне на елемент към опашката - push и изваждане на елемент от опашката - pop.
Реализация в STL:
queue<string> q;
q.push("Tom");
q.push("Dick");
q.push("Harry");
while (q.size() > 0)
{ cout << q.front() << "\n";
q.pop();
}
Пример:
// fifolifo.cpp
01: #include
<iostream> 02: #include <string>
03: #include <queue> 04: #include <stack> 06: using namespace std; 07: 08: int main() 09: { cout << "FIFO order:\n"; 11: 12: queue<string> q; 13: q.push("Tom"); 14: q.push("Dick"); 15: q.push("Harry"); 16: 17: stack<string> s; 18: while (q.size() > 0) 19: { string name = q.front(); 21: q.pop(); 22: cout << name << "\n"; 23: s.push(name); 24: } 26: cout << "LIFO order:\n"; 28: while (s.size() > 0) 29: { cout << s.top() << "\n"; 31: s.pop(); 32: } 34: return 0; 35: }

Други стандартни контейнери

* Множество (set) е контейнер (линейна структура от данни), което поддържа линейна наредба на елементите (независимо в какъв ред са въведени), като не допуска дублиращи се стойности.
// set.cpp
#include <iostream> #include <string> #include <set> using namespace std; int main() { set<string> s; s.insert("Tom"); s.insert("Dick"); s.insert("Tom"); // !!! s.insert("Harry"); cout << "set: " << endl; set<string>::iterator p; for (p = s.begin(); p!= s.end(); p++) cout << *p << "\n"; multiset<string> ms; ms.insert("Tom"); ms.insert("Dick"); ms.insert("Tom"); // !!! ms.insert("Harry"); cout << "multiset: " << endl; multiset<string>::iterator mp; for (mp = ms.begin(); mp!= ms.end(); mp++) cout << *mp << "\n"; cout << ms.size() << endl; cout << ms.count("Tom"); return 0; }

* Мултимножество (multiset) е подобно на множество, но допуска повече от едни елемент с една и съща стойност.

* Контейнер map съхранява двойки елементи и поддържа операция индекс.
map<string, double> scores;
scores["Tom"] = 90;
scores["Dick"] = 86;
scores["Harry"] = 100;
* Осигурява пряк и ефективен достъп до елементите.
// map.cpp
#include <iostream> #include <string> #include <map> using namespace std; int main() { map<string, int> scores; scores["Tom"] = 90; scores["Dick"] = 86; scores["Harry"] = 100; map<string, int>::iterator p; for (p = scores.begin(); p!= scores.end(); p++) cout << p->first << " " << p->second << "\n"; cout << scores.size() << endl; multimap<string, int> mmap; mmap.insert(pair<string, int>("Tom", 90)); mmap.insert(pair<string, int>("Dick", 86)); mmap.insert(pair<string, int>("Harry", 100)); mmap.insert(pair<string, int>("Tom", 190)); multimap<string, int>::iterator q; for (q = mmap.begin(); q!= mmap.end(); q++) cout << q->first << " " << q->second << "\n"; cout << mmap.size() << endl; return 0;
}

* Multimap е контайнер от двойки елементи - ключ, стойност, като се допускат елементи с еднакви ключове.
multimap<string, double> 
mmap;
mmap.insert(pair("Tom", 90));
mmap.insert(pair("Dick", 86));
mmap.insert(pair("Harry", 100));
mmap.insert(pair("Tom", 190));

Алгоритми в STL
*Причината за въвеждане и използване на итератори е отделянето на алгоритмите от структурите от данни.
* Алгоритмите в STL са реализирани от функции, които работят само с итератори и по такъв начин са независими от контейнерите, където се съхраняват данните.
* Пример: Функция, която намира сумата на елементите на контейнер - вектор или списък.
vector<double> data;
/* do something with data */

double vsum = 0;
accumulate(data.begin(), data.end(), vsum);
/* now vsum contains the sum of the elements in the vector */
list<double> salaries;
/* do something with salaries */

double lsum = 0;
accumulate(salaries.begin(), salaries.end(), lsum);
/* now lsum contains the sum of the elements in the list */
* Библиотеката поддържа функции за търсене.
/* search for a certain name on the staff */
list<string>::iterator it =
find(staff.begin(), staff.end(), name);
cout << *it << endl;

* Библиотеката поддържа функции за сортиране: sort, qsort