6.1-数据结构&算法-堆栈与队列
-----------------
第七课 堆栈与队列
一、数据结构的基本概念
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; }