6.1-資料結構&演算法-堆疊與佇列
阿新 • • 發佈:2018-11-26
-----------------
第七課 堆疊與佇列
一、資料結構的基本概念
1.邏輯結構
1)集合結構(集):結構中的元素除了同屬一個集之外,沒有任何聯絡。
2)線性結構(表):結構中的元素具有一對一的前後關係。
3)樹型結構(樹):結構中的元素具有一對多的父子關係。
4)網狀結構(圖):結構中的元素具有多對多的交叉對映關係。
2.物理結構
1)順序結構(陣列):結構中的元素存放在一段連續的地址空間中。隨機訪問方便,空間利用率低,插入刪除不便。
2)鏈式結構(鏈式):結構中的元素存放在彼此獨立的地址空間中,每個獨立的地址空間被稱為節點,節點除了儲存資料以外,還儲存另外一個或幾個相關節點的地址。空間利用率高,插入刪除方便,隨機訪問不便。
3.邏輯結構和物理結構的關係
表 樹 圖
順序 陣列 順序樹 復
鏈式 連結串列 鏈式樹 合
二、資料結構的基本運算
1.建立與銷燬
2.插入與刪除
3.獲取與修改
4.排序與查詢
三、堆疊
1.基本特徵:後進先出
2.基本操作:壓入(push),彈出(pop)
3.實現要點:初始化空間,棧頂指標,判空判滿。
1234
1*9^3+2*9^2+3*9^1+4*9^0 -> 4
123 -> 3
12 -> 2
1 -> 1
format.cpp
#include <iostream> #include <fstream> using namespace std; int main (void) { ofstream ofs ("format.txt"); if (! ofs) { perror ("開啟檔案失敗"); return -1; } ofs << 1234 << ' ' << 56.78 << ' ' << "tarena" << '\n'; ofs.close (); ofs.open ("format.txt", ios::app); if (! ofs) { perror ("開啟檔案失敗"); return -1; } ofs << "append_a_line\n"; ofs.close (); ifstream ifs ("format.txt"); if (! ifs) { perror ("開啟檔案失敗"); return -1; } int i; double d; string s1, s2; ifs>> i >> d >> s1 >> s2; cout << i << ' ' << d << ' ' << s1 << ' ' << s2 << endl; ifs.close (); return 0; }
istack.cpp
#include <iostream> using namespace std; // 基於鏈式表的堆疊 class Stack { public:// 構造過程中初始化為空堆疊 Stack (void) : m_top (NULL) {} // 析構過程中銷燬剩餘的節點 ~Stack (void) { for (Node* next; m_top; m_top = next) { next = m_top->m_next; delete m_top; } } // 壓入 void push (int data) { /* Node* node = new Node; node->m_data = data; node->m_next = m_top; m_top = node;*/ m_top = new Node (data, m_top); } // 彈出 int pop (void) { if (empty ()) throw UnderFlow (); int data = m_top->m_data; Node* next = m_top->m_next; delete m_top; m_top = next; return data; } // 判空 bool empty (void) const { return ! m_top; } private: // 下溢異常 class UnderFlow : public exception { const char* what (void) const throw () { return "堆疊下溢!"; } }; // 節點 class Node { public: Node (int data = 0, Node* next = NULL) : m_data (data), m_next (next) {} int m_data; // 資料 Node* m_next; // 後指標 }; Node* m_top; // 棧頂 }; int main (void) { try { Stack stack; for (int i = 0; i < 10; ++i) stack.push (i); while (! stack.empty ()) cout << stack.pop () << endl; // stack.pop (); } catch (exception& ex) { cout << ex.what () << endl; return -1; } return 0; }
putget.cpp
#include <iostream> #include <fstream> using namespace std; int main (void) { ofstream ofs ("putget.txt"); if (! ofs) { perror ("開啟檔案失敗"); return -1; } for (char c = ' '; c <= '~'; ++c) if (! ofs.put (c)) { perror ("寫入檔案失敗"); return -1; } ofs.close (); ifstream ifs ("putget.txt"); if (! ifs) { perror ("開啟檔案失敗"); return -1; } char c; while ((c = ifs.get ()) != EOF) cout << c; cout << endl; if (! ifs.eof ()) { perror ("讀取檔案失敗"); return -1; } ifs.close (); return 0; }
seek.cpp
#include <iostream> #include <fstream> using namespace std; int main (void) { fstream fs ("seek.txt", ios::in | ios::out); if (! fs) { perror ("開啟檔案失敗"); return -1; } fs << "0123456789"; cout << fs.tellp () << endl; cout << fs.tellg () << endl; fs.seekp (-3, ios::cur); fs << "XYZ"; fs.seekg (4, ios::beg); int i; fs >> i; cout << i << endl; cout << fs.tellg () << endl; cout << fs.tellp () << endl; fs.seekg (-6, ios::end); fs << "ABC"; fs.close (); return 0; }
stack.cpp
#include <iostream> using namespace std; // 基於順序表的堆疊 class Stack { public: // 構造過程中分配記憶體 Stack (size_t size = 10) : m_array (new int[size]), m_size (size), m_top (0) {} // 析構過程中釋放記憶體 ~Stack (void) { if (m_array) { delete[] m_array; m_array = 0; } } // 壓入 void push (int data) { if (full ()) throw OverFlow (); m_array[m_top++] = data; } // 彈出 int pop (void) { if (empty ()) throw UnderFlow (); return m_array[--m_top]; } // 判滿 bool full (void) const { return m_top >= m_size; } // 判空 bool empty (void) const { return ! m_top; } private: // 上溢異常 class OverFlow : public exception { const char* what (void) const throw () { return "堆疊上溢!"; } }; // 下溢異常 class UnderFlow : public exception { const char* what (void) const throw () { return "堆疊下溢!"; } }; int* m_array; // 陣列 size_t m_size; // 容量 size_t m_top; // 棧頂 }; void printb (unsigned int numb, int base) { Stack stack (256); do { stack.push (numb % base); } while (numb /= base); while (! stack.empty ()) { int digit = stack.pop (); if (digit < 10) cout << digit; else cout << char (digit - 10 + 'A'); } cout << endl; } int main (void) { try { Stack stack; for (int i = 0; ! stack.full (); ++i) stack.push (i); // stack.push (0); while (! stack.empty ()) cout << stack.pop () << endl; // stack.pop (); } catch (exception& ex) { cout << ex.what () << endl; return -1; } cout << "輸入一個整數:" << flush; int numb; cin >> numb; cout << "您想看幾進位制:" << flush; int base; cin >> base; cout << "結果:"; printb (numb, base); return 0; }
stream.cpp
#include <iostream> #include <iomanip> #include <cmath> #include <fstream> #include <sstream> using namespace std; int main (void) { cout << sqrt (2) << endl; cout.precision (10); // 10位有效數字 cout << sqrt (2) << endl; cout << sqrt (2) * 100 << endl; cout << setprecision (5) << sqrt (2) << endl << sqrt (2) * 100 << endl; cout << "當前精度:" << cout.precision () << endl; cout << setprecision (2) << 1.24 << ' ' << 1.25 << ' ' << 1.26 << endl; cout << showbase << hex << 127 << endl; cout << oct << 127 << endl; cout << dec << 127 << endl; cout << noshowbase << hex << 127 << dec << endl; cout << setw (12) << 127 << 721 << endl; cout << setfill ('$') << left << setw (12) << 127 << endl; cout.precision (10); cout.setf (ios::scientific); cout << sqrt (2) << endl; cout.setf (ios::fixed); cout << sqrt (2) << endl; cout << 12.00 << endl; cout << showpoint << 12.00 << endl; cout << noshowpoint << 12.00 << endl; ifstream ifs ("stream.txt"); ifs.unsetf (ios::skipws); char c; while (ifs >> c) cout << c; ifs.setf (ios::skipws); ifs.clear (); // 復位 ifs.seekg (ios::beg); while (ifs >> c) cout << c; ifs.close (); cout << endl; int i = 1234; double d = 56.78; string s = "tarena"; ostringstream oss; oss << i << ' ' << d << ' ' << s; string str = oss.str (); cout << str << endl; str = "hello 3.14 pai"; istringstream iss; iss.str (str); iss >> s >> d >> str; cout << s << ' ' << d << ' ' << str << endl; return 0; }
write.cpp
#include <iostream> #include <fstream> #include <cstring> using namespace std; class Dog { public: Dog (const string& name = "", int age = 0) : m_age (age) { strcpy (m_name, name.c_str ()); } void print (void) const { cout << m_name << "," << m_age << endl; } private: char m_name[128]; int m_age; }; int main (void) { ofstream ofs ("dog.dat"); Dog dog ("小白", 25); ofs.write ((char*)&dog, sizeof (dog)); ofs.close (); ifstream ifs ("dog.dat"); Dog dog2; ifs.read ((char*)&dog2, sizeof (dog2)); dog2.print (); ifs.close (); return 0; }
xor.cpp
#include <iostream> #include <fstream> #include <stdexcept> #include <cstdlib> using namespace std; #define BUFSIZE (1024*10) int _xor (const char* src, const char* dst, unsigned char key) { ifstream ifs (src, ios::binary); if (! ifs) { perror ("開啟原始檔失敗"); return -1; } ofstream ofs (dst, ios::binary); if (! ofs) { perror ("開啟目標檔案失敗"); return -1; } char* buf = NULL; try { buf = new char[BUFSIZE]; } catch (bad_alloc& ex) { cout << ex.what () << endl; return -1; } while (ifs.read (buf, BUFSIZE)) { for (size_t i = 0; i < BUFSIZE; ++i) buf[i] ^= key; if (! ofs.write (buf, BUFSIZE)) { perror ("寫入檔案失敗"); return -1; } } if (! ifs.eof ()) { perror ("讀取檔案失敗"); return -1; } for (size_t i = 0; i < ifs.gcount (); ++i) buf[i] ^= key; if (! ofs.write (buf, ifs.gcount ())) { perror ("寫入檔案失敗"); return -1; } delete[] buf; ofs.close (); ifs.close (); return 0; } int enc (const char* plain, const char* cipher) { srand (time (NULL)); unsigned char key = rand () % 256; if (_xor (plain, cipher, key) == -1) return -1; cout << "金鑰:" << (unsigned int)key << endl; return 0; } int dec (const char* cipher, const char* plain, unsigned char key) { return _xor (cipher, plain, key); } int main (int argc, char* argv[]) { if (argc < 3) { cerr << "用法:" << argv[0] << " <明文檔案> <密文檔案>" << endl; cerr << "用法:" << argv[0] << " <密文檔案> <明文檔案> <金鑰>" << endl; return -1; } if (argc < 4) return enc (argv[1], argv[2]); else return dec (argv[1], argv[2], atoi (argv[3])); return 0; }