חזור לתיקייה: תרגול

8 - עוד מהספרייה הסטנדרטית

חיפוש בתיקיה
Ctrl K
לחץ כאן או הקש Ctrl K כדי לחפש בכל התיקיה
  • כללי
  • איטרטורים והספריה הסטנדרטית
  • הספרייה algorithem

8 - עוד מהספרייה הסטנדרטית

02340124

מבוא לתכנות מערכות

רשימות תרגול לקריאה בשבת

עוד מהספרייה הסטנדרטית

הופק מתוך תקיית התואר של שקד

uni-folder.vercel.app

נסתכל כעת על עוד אוסף שיש לנו בספריה הסטנדרטית והוא std::liststd::liststd::list.
זהו אוסף המממש רשימה מקושרת דו כיוונית אשר מאפשרת:

  • הוספת איברים מהירה לכל מקום ברשימה.
  • גישה סדרתית קדימה ואחורה ברשימה

הרשימה אינה מאפשרת גישה מהירה למקום שרירותי בה.

חלקים גדולים מהממשק של listlistlist ו-vectorvectorvector משותפים וגם השימוש בממשק דומה, מה שמאפשר למשתמש להחליף בקלות את סוג האוסף שהוא משתמש בו, גם בשלב מאוחר בתכנות.
בפועל, vectorvectorvector הוא פתרון פשוט ויעיל ברוב המקרים ומומלץ להשתמש בו.

נסתכל על שיטות נבחרות מהמחלקה:

template <typename T>
class list
{
	list();
	list(const list& c);
	list(size_t num, const T& val = T());
	list& operator=(const list& c);
	~list();
	
	void push_back(const T& val);
	void pop_back();
	void push_front(const T& val);
	void pop_front();
	
	size_t size() const;
};

היצור הבא שנסתכל עליו הוא std::dequestd::dequestd::deque אשר הינו בעצם תור דו כיווני.
הוא כמו וקטור אך מאפשר הכנסה והוצאה מהירה משני הקצוות.

הממשק גם הוא דומה מאוד לוקטור.

דוגמה (לשימוש ב-dequedequedeque)

deque<string> words = { "Hello", "World" };

words.pop_front();
words.push_front("Hi");

נסתכל כעת על שני מבנים אסוציאטיביים אשר בהם סדר ההכנסה לא משפיע על סדר האיטרציה על האיברים:

  • הראשון מביניהם יהיה std::setstd::setstd::set השומר על איבריו בסדר ממוין באמצעות operator<operator<operator<.
    מבנה הנתונים זה מממש קבוצה ולכן אין בו כפילויות.
  • מבנה הנתונים std::mapstd::mapstd::map שומר זוגות של key⟼valuekey \longmapsto valuekey⟼value כאשר יש לכל היותר זוג אחד עם כל מפתח. (אין כפילויות מפתח)
    ניתן לבצע איטרציה על הזוגות השמורים ב-mapmapmap וניתן להשתמש ב-operator[  ]operator[\;]operator[] כדי לגשת לזוג עם מפתח נתון, כדי לשנות ערך השייך למפתח או כדי להכניס זוגות חדשים.
    ניתן בנוסף למצוא איבר באמצעות השיטה findfindfind אשר במידה והמפתח קיים, יוחזר האיטרטור המצביע לצמד המבוקש ובמידה ולא קיים, יוחזר איטרטור לסוף מבנה הנתונים המייצג כשלון או הצבעה לא חוקית.
תרגיל

נקבל קלט מהמשתמש ונספור את המילה הכי נפוצה שמופיעה בקלט.

void mostFequentWord()
{
	string word;
	map<string, int> count;
	int maxCount = 0;
	string maxWord = 0;
	
	while (cin >> word)
	{
		count[word]++;
		if (count[word] > maxCount)
		{
			maxCount = count[word];
			maxWord = word;
		}
	}
	
	cout << maxWord << endl;
}

איטרטורים והספריה הסטנדרטית

כמעט כל האוספים בספרייה הסטנדרטית מספקים איטרטור בעזרתו ניתן לעבור על איבריהם. האיטרטור מאפשר לנו גם לכתוב קוד אחיד אשר יכול לפעול על מספר אוספים.
כל אוסף מגדיר גם const_iteratorconst\_iteratorconst_iterator אשר ניתן באמצעותו לעבור על מבנה קבוע.
ניתן לקבל איטרטור קבוע למבנה לא קבוע באמצעות cbegin,cendcbegin,cendcbegin,cend.

אוספים שונים מספקים איטרטורים שונים:

  • האיטרטור של listlistlist הוא מסוג דו כיווני המאפשר ++++++ ו-−−--−−.
  • האיטרטור של וקטור הוא מסוג גישה רנדומלית ומאפשר בנוסף לפעולות הנ"ל גם קידום ונסיגה עם מספר שלם כלשהו וגם גישה עם האופרטור [  ][\;][] .
  • התיעוד של הספרייה הסטנדרטית מציין לכל אוסף את סוג האיטרטור שהוא מספק.

הספרייה algorithemalgorithemalgorithem

האיטרטורים שראינו זה עתה מאפשרים לנו להשתמש בממשק אחיד למספר אוספים ובנוסף, הספרייה הסטנדרטית מכילה מימושים מובנים למספר אלגוריתמים הפועלים על איטרטורים.

template <class Iterator, class T>
int std::count(Iterator first, Iterator last, cost T& value);

vector<int> numbers = {1, 5, 2, 5, 7};
cout << count(numbers.begin(), numbers.end(), 5); // prints 2

השימוש בספריה דורש את השורה #include <algorithem>.

חלק מהאלגוריתמים דורשים תמיכה בפעולות מסויימות מצד האיטרטורים. למשל, הפעולה sortsortsort דורשת שלאיטרטור יהיה operator[  ]operator[\;]operator[].

הערה

האלגוריתמים משתמשים תמיד במימוש היעיל ביותר לפי הפעולות שהאיטרטור תומך בהן.

חלק מהאלגוריתמים ניתנתים להתאמה באמצעות פרמטרים שלהם, למשל, מציאת כל האיברים המקיימים פרדיקט כלשהו ע"י הפונקציה any_ofany\_ofany_of.