数据结构与算法系列作业
一、顺序表与单链表
整个数据结构分为三个部分,Node类,LinkList类,SeqList类,Main函数,其中Main函数是测试两种链表的代码书写是否成立,LinkList类中的每个结点都是一个Node的实例,SeqList类单独成一例,用数组存储,已经写成模板的形式,我忘了以前不知道在哪里看过说用类模板的时候不能够将声明单独出来放在头文件中,所以我把声明和实现放在一起了。
Node.cpp
1 template<typename T> 2 class Node { 3 public: 4 Node() {} 5 Node(T data, Node<T> *ptr) :data(data), next(ptr) {} 6 ~Node() {} 7 T getData(); 8 void setData(T newData); 9 Node<T> *getNext(); 10 void setNext(Node<T> *ptr); 11 private: 12 T data; 13 Node<T> *next; 14 }; 15 template<typename T> 16 T Node<T>::getData() { 17 return data; 18 } 19 template<typename T> 20 void Node<T>::setData(T newData) { 21 data = newData; 22 } 23 template<typename T> 24 Node<T> *Node<T>::getNext() { 25 return next; 26 } 27 template<typename T> 28 void Node<T>::setNext(Node<T> *ptr) { 29 next = ptr; 30 }
LinkList.cpp
1 #include<iostream> 2 #include"Node.cpp" 3 template<typename T> 4 class LinkList { 5 public: 6 LinkList(); 7 LinkList(T array[], int n); 8 ~LinkList(); 9 void printList(); 10 void Insert(int i, T x); 11 int Length(); 12 T Get(int i); 13 Node<T> *getFirst() { return first; }; 14 int Locate(T x); 15 T Delete(int i); 16 void reverse(); 17 void add(T x); 18 private: 19 Node<T> *first; 20 }; 21 template<typename T> 22 LinkList<T>::LinkList() { 23 first = new Node<T>(); 24 first->setNext(NULL); 25 } 26 //尾插法构造链表 27 template<typename T> 28 LinkList<T>::LinkList(T array[], int n) { 29 first = new Node<T>(); 30 //first->setData(NULL); 31 first->setNext(NULL); 32 Node<T> *s, *r; 33 r = first; 34 for (int i = 0; i < n; i++) { 35 s = new Node<T>; 36 s->setData(array[i]); 37 r->setNext(s); 38 r = s; 39 } 40 } 41 //头插法构造链表 42 //template<typename T> 43 //LinkList<T>::LinkList(T array[], int n) { 44 // first = new Node<T>(); 45 // first->setData(NULL); 46 // first->setNext(NULL); 47 // Node<T> *s; 48 // for (int i = 0; i < n; i++) { 49 // s = new Node<T>; 50 // s->setData(array[i]); 51 // s->setNext(first->getNext()); 52 // first->setNext(s); 53 // } 54 //} 55 template<typename T> 56 LinkList<T>::~LinkList() { 57 while (first != NULL) { 58 Node<T> *q = first; 59 first = first->getNext(); 60 delete q; 61 } 62 } 63 template<typename T> 64 void LinkList<T>::printList() { 65 Node<T> *p = first->getNext(); 66 while (p != NULL) { 67 cout << p->getData() << " "; 68 p = p->getNext(); 69 } 70 cout << endl; 71 } 72 template<typename T> 73 void LinkList<T>::Insert(int index, T x) { 74 Node<T> *p = first; 75 Node<T> *s; 76 int count = 0; 77 while (p != NULL && count < index - 1) { 78 p = p->getNext(); 79 count++; 80 } 81 if (p == NULL) { 82 throw "在插入的位置前面有空结点,不能在所需序号处插入结点!"; 83 } 84 else { 85 s = new Node<T>; 86 s->setData(x); 87 s->setNext(p->getNext()); 88 p->setNext(s); 89 } 90 } 91 template<typename T> 92 int LinkList<T>::Length() { 93 int count = 0; 94 Node<T> *p = first->getNext(); 95 while (p != NULL) { 96 count++; 97 p = p->getNext(); 98 } 99 return count; 100 } 101 template<typename T> 102 T LinkList<T>::Get(int index) { 103 Node<T> *p = first->getNext(); 104 int count = 1; 105 while (p != NULL && count < index) { 106 p = p->getNext(); 107 count++; 108 } 109 if (p == NULL) { 110 throw "该位置为空结点!"; 111 } 112 else { 113 return p->getData(); 114 } 115 } 116 template<typename T> 117 int LinkList<T>::Locate(T x) { 118 Node<T> *p = first->getNext(); 119 int count = 1; 120 while (p != NULL) { 121 if (p->getData() == x) { 122 return count; 123 } 124 p = p->getNext(); 125 count++; 126 } 127 return 0; 128 } 129 template<typename T> 130 T LinkList<T>::Delete(int index) { 131 Node<T> *p = first; 132 int count = 0; 133 while (p != NULL && count < index - 1) { 134 p = p->getNext(); 135 count++; 136 } 137 if (p == NULL || p->getNext() == NULL) { 138 throw "被删的结点不存在!"; 139 } 140 else { 141 Node<T> *q = p->getNext(); 142 T x = q->getData(); 143 p->setNext(q->getNext()); 144 delete q; 145 return x; 146 } 147 } 148 template<typename T> 149 void LinkList<T>::reverse() { 150 //头结点 151 Node<T> *p = first; 152 //第一个结点 153 Node<T> *q = p->getNext(); 154 Node<T> *r; 155 while (q->getNext() != NULL) { 156 r = q->getNext(); 157 if (q == first->getNext()) { 158 q->setNext(NULL); 159 p = q; 160 q = r; 161 } 162 else { 163 //p->q->r 164 q->setNext(p); 165 p = q; 166 q = r; 167 } 168 } 169 q->setNext(p); 170 first->setNext(q); 171 } 172 template<typename T> 173 void LinkList<T>::add(T x) { 174 int length = Length(); 175 Insert(length+1, x); 176 }
SeqList.cpp
1 #include<iostream> 2 const int MaxSize = 10; 3 template<typename T> 4 class SeqList { 5 public: 6 SeqList() { length = 0; } 7 SeqList(T array[], int n); 8 ~SeqList() {} 9 int Length() { return length; } 10 T Get(int index); 11 int Locate(T x); 12 void Insert(int index, T x); 13 T Delete(int index); 14 void PrintList(); 15 void reverse(); 16 private: 17 T data[MaxSize]; 18 int length; 19 }; 20 template<typename T> 21 SeqList<T>::SeqList(T array[], int n) { 22 if (n > MaxSize) { 23 throw "数组的长度大于顺序表的长度!"; 24 } 25 else { 26 for (int i = 0; i < n; i++) { 27 data[i] = array[i]; 28 } 29 length = n; 30 } 31 } 32 template<typename T> 33 T SeqList<T>::Get(int index) { 34 if (index < 1 || index > length) { 35 throw "索引值不正确!"; 36 } 37 else { 38 return data[index - 1]; 39 } 40 } 41 template<typename T> 42 int SeqList<T>::Locate(T x) { 43 for (int i = 0; i < length; i++) { 44 if (data[i] == x) { 45 return i + 1; 46 } 47 } 48 return 0; 49 } 50 template<typename T> 51 void SeqList<T>::Insert(int index, T x) { 52 if (length >= MaxSize) { 53 throw"顺序表已满!"; 54 } 55 else if (index < 1 || index > length + 1) { 56 throw"索引值超出当前已有数据位置!"; 57 } 58 else { 59 for (int j = length; j >= index; j--) { 60 data[j] = data[j - 1]; 61 } 62 data[index - 1] = x; 63 length++; 64 } 65 } 66 template<typename T> 67 T SeqList<T>::Delete(int index) { 68 if (length == 0) { 69 throw "顺序表长度为0!"; 70 } 71 else if(index < 1 || index > length) { 72 throw"索引表超出当前已有数据位置!"; 73 } 74 else { 75 T x = data[index - 1]; 76 for (int j = index; j < length; j++) { 77 data[j - 1] = data[j]; 78 } 79 length--; 80 return x; 81 } 82 } 83 template<typename T> 84 void SeqList<T>::PrintList() { 85 for (int i = 0; i < length; i++) { 86 cout << data[i] << " "; 87 } 88 cout << endl; 89 } 90 template<typename T> 91 void SeqList<T>::reverse() { 92 for (int i = 0; i < length / 2 + 1; i++) { 93 T temp = data[i]; 94 data[i] = data[length - 1 - i]; 95 data[length - 1 - i] = temp; 96 } 97 }
main.cpp
#include"LinkList.cpp" #include"SeqList.cpp" using namespace std; /* 单链表main函数 */ int main() { //构造测试 int array1[] = { 1,3,5,7,9,10,12,14,16,18,20 }; int array2[] = { 2,4,6,8,11,13,15,16,17,19,20 }; LinkList<int> List1(array1, 11); //遍历测试 List1.printList(); LinkList<int> List2(array2, 11); //遍历测试 List2.printList(); //mergeLinkList(List1, List2); ////Insert测试 //try { // List.Insert(2, 6); // List.Insert(7, 6); // List.printList(); //} //catch (char *s) { // cout << s << endl; //} ////Length测试 //cout << "线性表的长度是:" << List.Length() << endl; ////Get测试 //try { // cout << "第5位的数字是:" << List.Get(5) << endl; // cout << "第8位的数字是:" << List.Get(8) << endl; //} //catch (char *s) { // cout << s << endl; //} ////Locate测试 //cout << List.Locate(6) << endl; ////Delete测试 //try{ // List.Delete(5); // List.printList(); //} //catch (char *s) { // cout << s << endl; //} //reverse测试 //List.reverse(); //List.printList(); system("pause"); return 0; } /* 顺序表main函数 */ //int main() { // int array[] = { 1,2,4,3,5,6,7 }; // //测试 // try { // SeqList<int> List(array, 7); // List.PrintList(); // cout << "顺序表的长度是:" << List.Length() << endl; // cout << "顺序表要查找的值是:" << List.Get(3) << endl; // cout << "顺序表中3所在的位置是:" << List.Locate(3) << endl; // cout << endl; // // List.Insert(4, 8); // List.PrintList(); // cout << "顺序表的长度是:" << List.Length() << endl; // cout << endl; // // List.Delete(4); // List.PrintList(); // cout << "顺序表的长度是:" << List.Length() << endl; // cout << endl; // // List.reverse(); // List.PrintList(); // } // catch (char *s) { // cout << s << endl; // } // system("pause"); // return 0; //}
二、双链表与循环链表
Node.cpp
1 template<typename T> 2 class Node { 3 public: 4 Node() {} 5 Node(T data, Node<T> *nextptr, Node<T> *priorptr) :data(data), next(nextptr), prior(priorptr) { 6 } 7 ~Node() {} 8 T getData(); 9 void setData(T newData); 10 Node<T> *getNext(); 11 void setNext(Node<T> *ptr); 12 Node<T> *getPrior(); 13 void setPrior(Node<T> *priorptr); 14 private: 15 T data; 16 Node<T> *next; 17 Node<T> *prior; 18 }; 19 template<typename T> 20 T Node<T>::getData() { 21 return data; 22 } 23 template<typename T> 24 void Node<T>::setData(T newData) { 25 data = newData; 26 } 27 template<typename T> 28 Node<T> *Node<T>::getNext() { 29 return next; 30 } 31 template<typename T> 32 void Node<T>::setNext(Node<T> *ptr) { 33 next = ptr; 34 } 35 template<typename T> 36 Node<T> *Node<T>::getPrior() { 37 return prior; 38 } 39 template<typename T> 40 void Node<T>::setPrior(Node<T> *priorptr) { 41 prior = priorptr; 42 }
DulList.cpp
1 #include"Node.cpp" 2 #include<iostream> 3 template<typename T> 4 class DulList { 5 public: 6 DulList(); 7 DulList(T array[], int n); 8 ~DulList(); 9 Node<T> *getFirst() { return first; } 10 void printList(); 11 void printListReverse(); 12 private: 13 Node<T> *first; 14 }; 15 template<typename T> 16 DulList<T>::DulList() { 17 first = new Node<T>; 18 first->setNext(first); 19 prior->setPrior(first); 20 } 21 template<typename T> 22 DulList<T>::DulList(T array[], int n) { 23 first = new Node<T>; 24 Node<T> *p = first; 25 p->setNext(NULL); 26 p->setPrior(NULL); 27 Node<T> *q; 28 for (int i = 0; i < n; i++) { 29 q = new Node<T>; 30 q->setData(array[i]); 31 p->setNext(q); 32 q->setPrior(p); 33 p = q; 34 } 35 p->setNext(first); 36 first->setPrior(p); 37 } 38 template<typename T> 39 DulList<T>::~DulList() { 40 Node<T> *p = first; 41 Node<T> *q; 42 while (p->getNext() != first) { 43 q = p->getNext(); 44 delete p; 45 p = q; 46 } 47 } 48 template<typename T> 49 void DulList<T>::printList() { 50 Node<T> *p = first->getNext(); 51 while (p != first) { 52 cout << p->getData() << " "; 53 p = p->getNext(); 54 } 55 cout << endl; 56 } 57 template<typename T> 58 void DulList<T>::printListReverse() { 59 Node<T> *p = first->getPrior(); 60 while (p != first) { 61 cout << p->getData() << " "; 62 p = p->getPrior(); 63 } 64 cout << endl; 65 }
CycleLinkList.cpp
1 #include<iostream> 2 #include"Node.cpp" 3 template<typename T> 4 class CycleLinkList { 5 public: 6 CycleLinkList(); 7 CycleLinkList(T array[], int length); 8 ~CycleLinkList(); 9 void printList(); 10 void add(T data); 11 private: 12 Node<T> *first; 13 }; 14 template<typename T> 15 CycleLinkList<T>::CycleLinkList() { 16 first = new Node<T>; 17 first->setNext(NULL); 18 } 19 template<typename T> 20 CycleLinkList<T>::CycleLinkList(T array[], int length) { 21 first = new Node<T>; 22 first->setNext(NULL); 23 Node<T> *p, *q; 24 p = first; 25 for (int i = 0; i < length; i++) { 26 q = new Node<T>; 27 q->setData(array[i]); 28 p->setNext(q); 29 p = q; 30 } 31 //循环单链表指针 32 p->setNext(first); 33 } 34 template<typename T> 35 CycleLinkList<T>::~CycleLinkList() { 36 Node<T> *p = first->getNext(); 37 Node<T> *q; 38 if (p == NULL) { 39 return; 40 } 41 else { 42 while (p != first) { 43 q = p->getNext(); 44 delete p; 45 p = q; 46 } 47 } 48 } 49 template<typename T> 50 void CycleLinkList<T>::printList() { 51 Node<T> *p = first->getNext(); 52 Node<T> *q; 53 if (p == NULL) { 54 cout << "空链表!" << endl; 55 } 56 else { 57 while (p != first) { 58 q = p->getNext(); 59 cout << p->getData() << " "; 60 p = q; 61 } 62 cout << endl; 63 } 64 } 65 template<typename T> 66 void CycleLinkList<T>::add(T data) { 67 Node<T> *p = first->getNext(); 68 //新节点 69 Node<T> *s; 70 s = new Node<T>; 71 s->setData(data); 72 if (p == NULL) { 73 first->setNext(s); 74 s->setNext(first); 75 return; 76 } 77 while (p->getNext() != first) { 78 p = p->getNext(); 79 } 80 s->setNext(first); 81 p->setNext(s); 82 }
三、栈
Node.cpp
1 template<typename T> 2 class Node { 3 public: 4 Node() {} 5 Node(T data, Node<T> *nextptr) :data(data), next(nextptr){ 6 } 7 ~Node() {} 8 T getData(); 9 void setData(T newData); 10 Node<T> *getNext(); 11 void setNext(Node<T> *ptr); 12 private: 13 T data; 14 Node<T> *next; 15 }; 16 template<typename T> 17 T Node<T>::getData() { 18 return data; 19 } 20 template<typename T> 21 void Node<T>::setData(T newData) { 22 data = newData; 23 } 24 template<typename T> 25 Node<T> *Node<T>::getNext() { 26 return next; 27 } 28 template<typename T> 29 void Node<T>::setNext(Node<T> *ptr) { 30 next = ptr; 31 }
顺序栈SeqStack.cpp
1 const int StackSize = 10; 2 template<typename T> 3 class SeqStack { 4 public: 5 SeqStack() { top = -1; } 6 ~SeqStack() {} 7 void Push(T x); 8 T Pop(); 9 T GetTop(); 10 bool Empty(); 11 bool Full(); 12 private: 13 T data[StackSize]; 14 int top; 15 }; 16 template<typename T> 17 void SeqStack<T>::Push(T x) { 18 if (Full()) { 19 throw "栈为满!"; 20 } 21 else { 22 data[++top] = x; 23 } 24 } 25 template<typename T> 26 T SeqStack<T>::Pop() { 27 if (Empty()) { 28 throw "栈为空!"; 29 } 30 else { 31 return data[top--]; 32 } 33 } 34 template<typename T> 35 T SeqStack<T>::GetTop() { 36 if (Empty()) { 37 throw "栈为空!"; 38 } 39 else { 40 return data[top]; 41 } 42 } 43 template<typename T> 44 bool SeqStack<T>::Empty() { 45 if (top == -1) { 46 return true; 47 } 48 else { 49 return false; 50 } 51 } 52 template<typename T> 53 bool SeqStack<T>::Full() { 54 if (top == StackSize - 1) { 55 return true; 56 } 57 else { 58 return false; 59 } 60 }
共享栈BothStack.cpp
1 const int StackSize = 10; 2 template <typename T> 3 class BothStack { 4 public: 5 BothStack() { top1 = -1; top2 = StackSize; } 6 ~BothStack() {} 7 void Push(int i, T x); 8 T Pop(int i); 9 T GetTop(int i); 10 bool Empty(); 11 bool Full(); 12 private: 13 T data[StackSize]; 14 int top1, top2; 15 }; 16 template<typename T> 17 void BothStack<T>::Push(int i, T x) { 18 if (top1 == top2 - 1) { 19 throw "栈为满!"; 20 } 21 else if (i == 1) { 22 data[++top1] = x; 23 } 24 else if (i == 2) { 25 data[--top2] = x; 26 } 27 else { 28 throw"输入的值有误,没有对应的栈!"; 29 } 30 } 31 template<typename T> 32 T BothStack<T>::Pop(int i) { 33 if (i == 1) { 34 if (top1 == -1) { 35 throw"栈1为空!"; 36 } 37 else { 38 return data[top1--]; 39 } 40 } 41 else if (i == 2) { 42 if (top2 == StackSize) { 43 throw"栈2为空!"; 44 } 45 else { 46 return data[top2++]; 47 } 48 } 49 else { 50 throw"输入的值有误,没有对应的栈!"; 51 } 52 } 53 template<typename T> 54 T BothStack<T>::GetTop(int i) { 55 if (i == 1) { 56 if (top1 == -1) { 57 throw"栈1为空!"; 58 } 59 else { 60 return data[top1]; 61 } 62 } 63 else if (i == 2) { 64 if (top2 == StackSize) { 65 throw"栈2为空!"; 66 } 67 else { 68 return data[top2]; 69 } 70 } 71 else { 72 throw"输入的值有误,没有对应的栈!"; 73 } 74 } 75 template<typename T> 76 bool BothStack<T>::Empty() { 77 if (top1 == -1 && top2 == StackSize) { 78 return true; 79 } 80 else { 81 return false; 82 } 83 } 84 template<typename T> 85 bool BothStack<T>::Full() { 86 if (top1 == top2 - 1) { 87 return true; 88 } 89 else { 90 return false; 91 } 92 }
链栈LinkStack.cpp
1 #include<iostream> 2 using namespace std; 3 #include"Node.cpp" 4 template<typename T> 5 class LinkStack { 6 public: 7 LinkStack(); 8 ~LinkStack(); 9 void Push(T x); 10 T Pop(); 11 T GetTop(); 12 bool Empty(); 13 private: 14 Node<T> *top; 15 }; 16 template<typename T> 17 LinkStack<T>::LinkStack() { 18 top = NULL; 19 } 20 template<typename T> 21 LinkStack<T>::~LinkStack() { 22 Node<T> *temp; 23 while (top != NULL) { 24 temp = top; 25 top = top->getNext(); 26 delete temp; 27 } 28 } 29 template<typename T> 30 void LinkStack<T>::Push(T x) { 31 Node<T> *temp = new Node<T>; 32 temp->setData(x); 33 temp->setNext(top); 34 top = temp; 35 } 36 template<typename T> 37 T LinkStack<T>::Pop() { 38 if (Empty()) { 39 throw"栈为空!"; 40 } 41 else { 42 T x = top->getData(); 43 Node<T> *temp = top; 44 top = top->getNext(); 45 delete temp; 46 return x; 47 } 48 } 49 template<typename T> 50 T LinkStack<T>::GetTop() { 51 if (Empty()) { 52 throw"栈为空!"; 53 } 54 else { 55 return top->getData(); 56 } 57 } 58 template<typename T> 59 bool LinkStack<T>::Empty() { 60 if (top == NULL) { 61 return true; 62 } 63 else { 64 return false; 65 } 66 }
main.cpp
1 /* 2 顺序栈测试文件 3 */ 4 //#include<iosteam> 5 //using namespace std; 6 //#include"SeqStack.cpp" 7 //int main() { 8 // SeqStack<int> stack; 9 // int array[] = { 1,2,3,4,5,6,7,8,9,10,11,12}; 10 // try { 11 // for (int i = 0; i < 12; i++) { 12 // stack.Push(array[i]); 13 // } 14 // } 15 // catch(char *s){ 16 // cout << s << endl; 17 // while (!stack.Empty()) { 18 // cout << stack.Pop() << endl; 19 // } 20 // } 21 // system("pause"); 22 // return 0; 23 //} 24 /* 25 共享栈测试文件 26 */ 27 //#include<iosteam> 28 //using namespace std; 29 //#include"BothStack.cpp" 30 //int main() { 31 // BothStack<int> bothstack; 32 // int array[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13}; 33 // try { 34 // for (int i = 0; i < 13; i++) { 35 // bothstack.Push(1,array[i]); 36 // bothstack.Push(2, array[12 - i]); 37 // } 38 // } 39 // catch (char *s) { 40 // cout << s << endl; 41 // while (!bothstack.Empty()) { 42 // cout << bothstack.Pop(1) << " " << bothstack.Pop(2) << endl; 43 // } 44 // } 45 // system("pause"); 46 // return 0; 47 //} 48 /* 49 链栈测试文件 50 */ 51 #include"LinkStack.cpp" 52 int main() { 53 LinkStack<int> linkstack; 54 try { 55 linkstack.Push(1); 56 linkstack.Push(2); 57 cout << linkstack.GetTop() << endl; 58 cout << linkstack.Pop() << endl; 59 cout << linkstack.Pop() << endl; 60 cout << linkstack.Pop() << endl; 61 } 62 catch(char *s){ 63 cout << s << endl; 64 } 65 if (linkstack.Empty()) { 66 cout << "栈为空!" << endl; 67 } 68 system("pause"); 69 return 0; 70 }
在这次的作业中还用的一种叫做指针栈的东西,指针栈是我起的名字,因为是一种通过指针实现的栈,即在内存中开辟一块连续的空间做栈的操作,与数组实现的会稍微有一些不同。
分析:其实本质上来说就是在一段连续的内存空间中实现一个栈,之前实现栈数据结构的时候使用的存储结构是数组,而这次使用的是指针。与数组存储不同的时候,这个时候的数指针不可以设置为-1,因为会产生指针指向越界,也不可以将指针设置超过最大值,也是会产生指针指向越界。
因此在这里我使用了两个指针,一个是bottom,另外一个是top。一个数据存放栈的最大值MaxLength,另外用两个标志FlagBottom和FlagTop,专门用于处理判定栈空和栈满时对应的位置是否存放有数据值。如果top==bottom并且FlagBottom为false,那么栈底就是真正的空,如果此时为True,证明栈底还是有数据的。如果top-bottom==MaxLength-1并且FlagTop为True,证明栈满了,如果为false,证明这个位置没有存放数据,可以继续放数据。需要注意的是,指针指向的是一个地址的开端,所以指向栈顶的时候要减去1的地址值,否则就会出现指针越界。通过这样指示实现不浪费空间,按照分配的内存大小来存放所需的数据量,代码实现如下。
PointerStack.cpp
1 template<typename T> 2 class PointerStack { 3 public: 4 PointerStack() {}; 5 PointerStack(int n); 6 ~PointerStack(); 7 void push(T data); 8 T pop(); 9 T get(); 10 bool Full(); 11 bool Empty(); 12 private: 13 T *bottom,*top; 14 //记录长度 15 int MaxLength; 16 //标记栈底和栈顶数据空间是否有数据 17 bool FlagBottom; 18 bool FlagTop; 19 }; 20 template<typename T> 21 PointerStack<T>::PointerStack(int n) { 22 bottom = new T[n]; 23 top = bottom; 24 FlagBottom = FlagTop = false; 25 MaxLength = n; 26 } 27 template<typename T> 28 PointerStack<T>::~PointerStack() { 29 delete[] bottom; 30 } 31 template<typename T> 32 void PointerStack<T>::push(T data) { 33 if (Full()) {throw "栈满!";} 34 else if (top == bottom) { 35 *(top++) = data; 36 FlagBottom = true; 37 } 38 //进入最后一个空白空间 39 else if(top - bottom == MaxLength - 1){ 40 *top = data; 41 FlagTop = true; 42 } 43 else {*(top++) = data;} 44 } 45 template<typename T> 46 T PointerStack<T>::pop() { 47 if (Empty()) {throw "栈空!";} 48 else if (top == bottom) { 49 T data = *top; 50 FlagBottom = false; 51 return data; 52 } 53 //进入最后一个空白空间 54 else if (top - bottom == MaxLength - 1) { 55 T data = *(top--); 56 FlagTop = false; 57 return data; 58 } 59 else { 60 T data = *(top--); 61 return data; 62 } 63 } 64 template<typename T> 65 T PointerStack<T>::get() { 66 if (Empty()) {throw "栈空!";} 67 else {return *top;} 68 } 69 template<typename T> 70 bool PointerStack<T>::Empty() { 71 if ((top == bottom) && !FlagBottom) {return true;} 72 else {return false;} 73 } 74 template<typename T> 75 bool PointerStack<T>::Full() { 76 if ((top - bottom == MaxLength - 1)&& FlagTop) {return true;} 77 else {return false;} 78 }
四、队列
Node.cpp
1 template<typename T> 2 class Node { 3 public: 4 Node() {} 5 Node(T data, Node<T> *nextptr) :data(data), next(nextptr) { 6 } 7 ~Node() {} 8 T getData(); 9 void setData(T newData); 10 Node<T> *getNext(); 11 void setNext(Node<T> *ptr); 12 private: 13 T data; 14 Node<T> *next; 15 }; 16 template<typename T> 17 T Node<T>::getData() { 18 return data; 19 } 20 template<typename T> 21 void Node<T>::setData(T newData) { 22 data = newData; 23 } 24 template<typename T> 25 Node<T> *Node<T>::getNext() { 26 return next; 27 } 28 template<typename T> 29 void Node<T>::setNext(Node<T> *ptr) { 30 next = ptr; 31 }
LinkQueue.cpp
1 #include"Node.cpp" 2 #include<iostream> 3 template<typename T> 4 class LinkQueue { 5 public: 6 LinkQueue(); 7 LinkQueue(T array[], int n); 8 ~LinkQueue(); 9 void EnQueue(T x); 10 T DeQueue(); 11 T GetQueue(); 12 bool QueueEmpty(); 13 private: 14 Node<T> *front; //队头指针,指向头节点 15 Node<T> *rear; //队尾指针,指向终端节点 16 }; 17 template<typename T> 18 LinkQueue<T>::LinkQueue() { 19 Node<T> *s = new Node<T>; 20 s->setNext(NULL); 21 front = s; 22 rear = s; 23 } 24 template<typename T> 25 LinkQueue<T>::LinkQueue(T array[], int n) { 26 Node<T> *s; 27 front = new Node<T>; 28 rear = front; 29 rear->setNext(NULL); 30 for (int i = 0; i < n; i++) { 31 s = new Node<T>; 32 s->setData(array[i]); 33 s->setNext(NULL); 34 rear->setNext(s); 35 rear = s; 36 } 37 38 } 39 template<typename T> 40 LinkQueue<T>::~LinkQueue() { 41 Node<T> *p = front; 42 Node<T> *q = p->getNext(); 43 while (q != NULL) { 44 delete p; 45 p = q; 46 q = q->getNext(); 47 } 48 delete p; //删除最后一个节点 49 } 50 template<typename T> 51 void LinkQueue<T>::EnQueue(T x) { 52 Node<T> *s = new Node<T>; 53 s->setData(x); 54 s->setNext(NULL); 55 rear->setNext(s); 56 rear = s; 57 } 58 template<typename T> 59 T LinkQueue<T>::DeQueue() { 60 Node<T> *s; 61 if (rear == front) { 62 throw "链表为空!"; 63 } 64 else { 65 s = front->getNext(); 66 T x = s->getData(); 67 front->setNext(s->getNext()); 68 if (s->getNext() == NULL) { 69 rear = front; 70 } 71 delete s; 72 return x; 73 } 74 } 75 template<typename T> 76 T LinkQueue<T>::GetQueue() { 77 if (rear == front) { 78 throw "链表为空!"; 79 } 80 else { 81 return front->getNext()->getData(); 82 } 83 } 84 template<typename T> 85 bool LinkQueue<T>::QueueEmpty() { 86 if (front == rear) { 87 return true; 88 } 89 else { 90 return false; 91 } 92 }
CirQueue.cpp
1 const int QueueSize = 5; 2 template<typename T> 3 class CirQueue { 4 public: 5 CirQueue(); 6 ~CirQueue() {}; 7 void EnQueue(T x); 8 T DeQueue(); 9 T GetQueue(); 10 private: 11 T data[QueueSize]; 12 int front, rear; 13 }; 14 template<typename T> 15 CirQueue<T>::CirQueue() { 16 rear = front = QueueSize - 1; 17 } 18 template<typename T> 19 void CirQueue<T>::EnQueue(T x) { 20 if ((rear + 1) % QueueSize == front) { 21 throw "队列已满!"; 22 } 23 else { 24 rear = (rear + 1) % QueueSize; 25 data[rear] = x; 26 } 27 } 28 template<typename T> 29 T CirQueue<T>::DeQueue() { 30 if (rear == front) { 31 throw "队列已空!"; 32 } 33 else { 34 front = (front + 1) % QueueSize; 35 return data[front]; 36 } 37 } 38 template<typename T> 39 T CirQueue<T>::GetQueue() { 40 if (rear == front) { 41 throw "队列已空!"; 42 } 43 else { 44 int i = (front + 1) % QueueSize; 45 return data[i]; 46 } 47 }
五、第一次上机作业
主要是对单链表、双链表和循环链表的一些操作。
1 #include<iostream> 2 using namespace std; 3 /* 4 1. 定义双链表的节点结构 5 */ 6 template<typename DataType> 7 struct DulNode { 8 DataType data; 9 DulNode<DataType> *prior, *next; 10 }; 11 /* 12 2. 定义外部函数初始化双链表 13 */ 14 template<typename DataType> 15 void newLink(DulNode<DataType> *first) { 16 first->data = NULL; 17 first->prior = first; 18 first->next = first; 19 } 20 /* 21 3. 定义外部函数实现双链表的尾插入 22 */ 23 template<typename DataType> 24 void TailInsert(DulNode<DataType> *first, DataType c) { 25 DulNode<DataType> *p, *s; 26 p = first->prior; 27 s = new DulNode<DataType>; 28 s->data = c; 29 //p->s->first 30 s->next = p->next; 31 s->prior = p; 32 first->prior = s; 33 p->next = s; 34 } 35 /* 36 4. 定义外部函数实现将整个双链表对称 37 */ 38 template<typename DataType> 39 void ExchangeSentence(DulNode<DataType> *p, DulNode<DataType> *q) { 40 DulNode<DataType> *p1 = p->prior; 41 DulNode<DataType> *q1 = q->prior; 42 DulNode<DataType> *s; 43 while (p1 != p) { 44 s = new DulNode<DataType>; 45 s->data = p1->data; 46 //插入链表时的指针调整 47 s->next = q; 48 s->prior = q1; 49 q1->next = s; 50 q->prior = s; 51 //工作指针调整 52 q1 = s; 53 p1 = p1->prior; 54 } 55 } 56 /* 57 5. 临时正向打印函数 58 */ 59 template<typename DataType> 60 void printDulLink(DulNode<DataType> *first) { 61 DulNode<DataType> *p = first->next; 62 while (p != first) { 63 cout << p->data << " "; 64 p = p->next; 65 } 66 cout << endl; 67 } 68 /* 69 临时反向打印函数 70 */ 71 template<typename DataType> 72 void printRevDulLink(DulNode<DataType> *first) { 73 DulNode<DataType> *p = first->prior; 74 while (p != first) { 75 cout << p->data << " "; 76 p = p->prior; 77 } 78 cout << endl; 79 } 80 /* 81 6. 扫描指针使得对每个单词进行反转 82 */ 83 template<typename DataType> 84 void ExchangeWords(DulNode<DataType> *p1) { 85 DulNode<DataType> *s1 = p1->next; 86 DulNode<DataType> *s2 = s1->next; 87 DataType temp = NULL; 88 while (s1 != p1) { 89 while (s1->data != ' ') { 90 //开始读单词 91 s2 = s1; 92 while (s2->next->data != ' ' && s2->next != p1) { 93 s2 = s2->next; 94 } 95 //交换数据 96 temp = s1->data; 97 s1->data = s2->data; 98 s2->data = temp; 99 //调整指针位置 100 s1 = s2; 101 break; 102 } 103 //继续扫描 104 s1 = s1->next; 105 } 106 } 107 /* 108 临时析构函数 109 */ 110 template<typename DataType> 111 void deleteDulLink(DulNode<DataType> *first) { 112 DulNode<DataType> *p = first->next; 113 DulNode<DataType> *q = p->next; 114 while (q != first->next) { 115 delete p; 116 p = q; 117 q = q->next; 118 } 119 }
六、第二次上机作业
迷宫问题,用一个二维数组表示迷宫,1表示墙壁不可走,0表示通路可走,找出起点到终点超过20条路径。
迷宫是下面这个样子的,用(a,b)表示起点,其中a和b是数组的索引值,(c,d)表示终点值,所以要传入四个参数进搜索的路径的函数中。注意数组的索引是从0开始的!
1 int main() { 2 SeqStack st; 3 int mg[10][10] = 4 { 5 {1,1,1,1,1,1,1,1,1,1}, 6 {1,0,0,1,0,0,0,0,0,1}, 7 {1,0,0,1,0,0,0,1,0,1}, 8 {1,0,0,0,0,1,1,0,0,1}, 9 {1,0,1,1,1,0,0,0,0,1}, 10 {1,0,0,0,1,0,0,0,0,1}, 11 {1,0,1,1,1,0,1,1,0,1}, 12 {1,1,0,0,0,0,0,0,0,1}, 13 {1,1,1,1,1,1,1,1,1,1} 14 }; 15 mgPath(1, 2, 5, 6, st,mg); 16 system("pause"); 17 return 0; 18 }
SeqStack.h
1 #pragma once 2 #include<iostream> 3 const int StackSize = 100; 4 struct currentPosition { 5 //无参构造函数 6 currentPosition() {}; 7 //有参构造函数 8 currentPosition(int i, int j, int di) :m_i(i), m_j(j), m_di(di) {} 9 int m_i; //x方向 10 int m_j; //y方向 11 int m_di; //存储从其出发已经走过的方向,0,1,2,3代表四个方向 12 }; 13 class SeqStack { 14 public: 15 SeqStack() { top = -1; } 16 ~SeqStack() {} 17 bool Empty(); 18 bool Full(); 19 void printStack(); 20 void Push(currentPosition x); 21 currentPosition Pop(); 22 currentPosition GetTop(); 23 private: 24 currentPosition data[StackSize]; 25 int top; 26 };
SeqStack.cpp
1 #include"SeqStack.h" 2 void SeqStack::Push(currentPosition x) { 3 if (Full()) { 4 throw "栈为满!"; 5 } 6 else { 7 data[++top] = x; 8 } 9 } 10 currentPosition SeqStack::Pop() { 11 if (Empty()) { 12 throw "栈为空!"; 13 } 14 else { 15 return data[top--]; 16 } 17 } 18 currentPosition SeqStack::GetTop() { 19 if (Empty()) { 20 throw "栈为空!"; 21 } 22 else { 23 return data[top]; 24 } 25 } 26 bool SeqStack::Empty() { 27 if (top == -1) { 28 return true; 29 } 30 else { 31 return false; 32 } 33 } 34 bool SeqStack::Full() { 35 if (top == StackSize - 1) { 36 return true; 37 } 38 else { 39 return false; 40 } 41 } 42 void SeqStack::printStack() { 43 for (int i = 0; i <= top; i++) { 44 std::cout << "(" << data[i].m_i << "," << data[i].m_j << ") "; 45 } 46 std::cout << std::endl; 47 }
mgPath.cpp
1 #include"SeqStack.h" 2 #include<iostream> 3 using namespace std; 4 //(xi,yi)为起点,(xe,ye)为终点 5 int mgPath(int xi, int yi, int xe, int ye,SeqStack &stack,int &mg[10][10]){ 6 int i = xi, j = yi, di=-1; //存放当前格的信息的临时变量 7 int count = 0; //控制打印条数 8 int find; //标志从当前结点出发是否有可行的下一站 9 currentPosition start(xi, yi, -1); 10 stack.Push(start); //起始节点入栈 11 mg[xi][yi] = -1; //-1表示不重复走路 12 while (!stack.Empty()) { 13 currentPosition temp = stack.GetTop(); 14 if (temp.m_i == xe && temp.m_j == ye) { 15 if (count < 10) { 16 count++; 17 stack.printStack(); 18 stack.Pop(); 19 //初始化记录变量 20 i = stack.GetTop().m_i; 21 j = stack.GetTop().m_j; 22 di = stack.GetTop().m_di; 23 mg[temp.m_i][temp.m_j] = 0; //取消禁走令 24 } 25 else { 26 return 0; 27 } 28 } 29 find = 0; //准备测试从(i,j)出发是否可以往下走 30 while (di < 4 && find == 0) { //找下一个网格 31 di++; //试探下一种走法 32 switch (di) 33 { 34 case 0://向上 35 i = temp.m_i - 1; 36 j = temp.m_j; 37 break; 38 case 1://向右 39 i = temp.m_i; 40 j = temp.m_j + 1; 41 break; 42 case 2://向下 43 i = temp.m_i + 1; 44 j = temp.m_j; 45 break; 46 case 3://向左 47 i = temp.m_i; 48 j = temp.m_j - 1; 49 break; 50 } 51 if (mg[i][j] == 0) { find = 1; }//没被禁走找到下一站 52 } 53 if (find == 1) { 54 currentPosition top = stack.Pop(); 55 top.m_di = di; 56 stack.Push(top); 57 currentPosition temp2(i, j, -1); 58 stack.Push(temp2); 59 mg[i][j] = -1; 60 //初始化记录变量 61 i = stack.GetTop().m_i; 62 j = stack.GetTop().m_j; 63 di = stack.GetTop().m_di; 64 } 65 else { 66 mg[stack.GetTop().m_i][stack.GetTop().m_j] = 0; 67 stack.Pop(); 68 //初始化记录变量 69 i = stack.GetTop().m_i; 70 j = stack.GetTop().m_j; 71 di = stack.GetTop().m_di; 72 } 73 } 74 return 0; 75 }
六、第3次上机作业
利用队列来找两点之间的最短距离,这是我写CPP代码以来最不舒服的一次,完全没有CPP的规范可言。
Cirqueue.cpp
1 const int QueueSize = 15; 2 template<typename T> 3 class CirQueue { 4 public: 5 CirQueue(); 6 ~CirQueue() {}; 7 void EnQueue(T x); 8 T DeQueue(); 9 T GetQueue(); 10 bool Full(); 11 bool Empty(); 12 int getfront(); 13 int getrear(); 14 T getData(); 15 T data[QueueSize]; 16 int front, rear; 17 }; 18 template<typename T> 19 CirQueue<T>::CirQueue() { 20 rear = front = QueueSize - 1; 21 } 22 template<typename T> 23 void CirQueue<T>::EnQueue(T x) { 24 if ((rear + 1) % QueueSize == front) { 25 throw "队列已满!"; 26 } 27 else { 28 rear = (rear + 1) % QueueSize; 29 data[rear] = x; 30 } 31 } 32 template<typename T> 33 T CirQueue<T>::DeQueue() { 34 if (rear == front) { 35 throw "队列已空!"; 36 } 37 else { 38 front = (front + 1) % QueueSize; 39 return data[front]; 40 } 41 } 42 template<typename T> 43 T CirQueue<T>::GetQueue() { 44 if (rear == front) { 45 throw "队列已空!"; 46 } 47 else { 48 int i = (front + 1) % QueueSize; 49 return data[i]; 50 } 51 } 52 template<typename T> 53 bool CirQueue<T>::Full() { 54 if ((rear + 1) % QueueSize == front) { 55 return true; 56 } 57 else { 58 return false; 59 } 60 } 61 template<typename T> 62 bool CirQueue<T>::Empty() { 63 if (rear == front) { 64 return true; 65 } 66 else { 67 return false; 68 } 69 } 70 template<typename T> 71 int CirQueue<T>::getfront() { 72 return front; 73 } 74 template<typename T> 75 int CirQueue<T>::getrear() { 76 return rear; 77 } 78 template<typename T> 79 T CirQueue<T>::getData() { 80 return data; 81 }
main.cpp
1 #include<iostream> 2 using namespace std; 3 #include"CirQueue.cpp" 4 struct QNode { 5 int j; //顶点编号 6 int f; //当前顶点在该路径上的父结点在队列中的位置 7 }; 8 void print(int &Martix[5]) { 9 for (int i = 0; i < 5; i++) { 10 cout << Martix[i] << " "; 11 } 12 cout << endl; 13 } 14 int main() { 15 int A[5][5] = { 16 {-1,1,-1,3,10}, 17 {-1,-1,5,-1,-1}, 18 {-1,-1,-1,-1,1}, 19 {-1,-1,2,-1,6}, 20 {-1,-1,-1,-1,-1} 21 }; //图结构 22 int R[5] = { 1000,1000,1000,1000,1000 }; //存储源点到各其他点的距离值(动态更新) 23 int P[5] = { -1,-1,-1,-1,-1 }; //当前路径终点在队列中的位置 24 CirQueue<QNode> Q; //定义队列 25 QNode W; //定义队列中的当前结点 26 W.j = 0; //结点编号为0 27 W.f = -1; //结点没有父结点 28 R[0] = 0; //结点到0的距离为0 29 Q.EnQueue(W); //第一个结点入队 30 while (!Q.Empty()) { 31 W = Q.DeQueue(); 32 int s = W.j; //拿到当前结点的编号 33 int f = Q.getfront(); //拿到头节点在队列中的位置 34 for (int i = 0; i < 5; i++) { 35 if (A[s][i] != -1) { 36 if (R[s] + A[s][i] <= R[i]) {//比较新路径的存储距离 37 W.j = i; 38 W.f = f; 39 Q.EnQueue(W); 40 R[i] = R[s] + A[s][i]; 41 P[i] = Q.getrear(); 42 } 43 } 44 } 45 } 46 for (int i = 1; i < 5; i++) { 47 cout << "0到" << i << "的最短距离为:" << R[i] << endl; 48 int shortest = R[i]; 49 int j = P[i]; 50 int Path[5] = { 0 }; 51 int k = 4; 52 Path[k] = Q.data[j].j; 53 k--; 54 while (Q.data[j].f != -1) { 55 j = Q.data[j].f; 56 Path[k] = Q.data[j].j; 57 k--; 58 } 59 print(Path); 60 } 61 system("pause"); 62 return 0; 63 }
七、第4次上机作业
建立一棵二叉树,并完成所有的遍历方式。
BiTree.cpp
1 #include<iostream> 2 using namespace std; 3 template<class DataType> 4 struct BiNode 5 { 6 DataType data; 7 BiNode<DataType> *lchild, *rchild; 8 }; 9 template<class DataType> 10 struct QuNode 11 { 12 BiNode<DataType> *curNode; 13 int level; 14 }; 15 template<class DataType> 16 class BiTree 17 { 18 public: 19 BiTree() { root = Create(root); } 20 ~BiTree() { Release(root); } 21 void PreOrder() { PreOrder(root); } 22 void InOrder() { InOrder(root); } 23 void PostOrder() { PostOrder(root); } 24 void LeverOrder(); 25 void LeverOrderh(); 26 private: 27 BiNode<DataType> *root; //指向根结点的头指针 28 BiNode<DataType> *Create(BiNode<DataType> *bt); //调用构造函数 29 void Release(BiNode<DataType> *bt); //析构函数调用 30 void PreOrder(BiNode<DataType> *bt); //前序遍历 31 void InOrder(BiNode<DataType> *bt); //中序遍历 32 void PostOrder(BiNode<DataType> *bt); //后序遍历 33 }; 34 template<class DataType> 35 BiNode<DataType> *BiTree<DataType>::Create(BiNode<DataType> *bt) 36 { 37 char ch; //字符编号 38 cin >> ch; 39 if (ch == '#') 40 { 41 bt = NULL; 42 } 43 else 44 { 45 bt = new BiNode<DataType>; 46 bt->data = ch; 47 bt->lchild = Create(bt->lchild); 48 bt->rchild = Create(bt->rchild); 49 } 50 return bt; 51 } 52 template<class DataType> 53 void BiTree<DataType>::Release(BiNode<DataType> *bt) 54 { 55 if (bt != NULL) 56 { 57 Release(bt->lchild); 58 Release(bt->rchild); 59 delete bt; 60 } 61 } 62 template<class DataType> 63 void BiTree<DataType>::PreOrder(BiNode<DataType> *bt) 64 { 65 if(bt==NULL) 66 { 67 return; 68 } 69 else 70 { 71 cout << bt->data; 72 PreOrder(bt->lchild); 73 PreOrder(bt->rchild); 74 } 75 } 76 template<class DataType> 77 void BiTree<DataType>::InOrder(BiNode<DataType> *bt) 78 { 79 if (bt == NULL) 80 { 81 return; 82 } 83 else 84 { 85 InOrder(bt->lchild); 86 cout << bt->data; 87 InOrder(bt->rchild); 88 } 89 } 90 template<class DataType> 91 void BiTree<DataType>::PostOrder(BiNode<DataType> *bt) 92 { 93 if (bt == NULL) 94 { 95 return; 96 } 97 else 98 { 99 PostOrder(bt->lchild); 100 PostOrder(bt->rchild); 101 cout << bt->data; 102 } 103 } 104 template<class DataType> 105 void BiTree<DataType>::LeverOrder() 106 { 107 BiNode<DataType> *Q[100]; 108 BiNode<DataType> *q; 109 int front = -1; 110 int rear = -1; 111 if (root == NULL) 112 { 113 return; 114 } 115 Q[++rear] = root; 116 while (front != rear) 117 { 118 q = Q[++front]; 119 cout << q->data; 120 if (q->lchild != NULL) 121 { 122 Q[++rear] = q->lchild; 123 } 124 if (q->rchild != NULL) 125 { 126 Q[++rear] = q->rchild; 127 } 128 } 129 } 130 template<class DataType> 131 void BiTree<DataType>::LeverOrderh() 132 { 133 QuNode<DataType> Q[100]; 134 QuNode<DataType> q; 135 int front = -1; 136 int rear = -1; 137 if (root == NULL) 138 { 139 return; 140 } 141 Q[++rear].curNode = root; //根结点入队 142 Q[rear].level = 1; //根结点的层数 143 while (front != rear) 144 { 145 q = Q[++front]; 146 cout << "结点"<<q.curNode->data<<"的层数为:" << q.level << endl; 147 if (q.curNode->lchild != NULL) 148 { 149 Q[++rear].curNode = q.curNode->lchild; 150 Q[rear].level = q.level + 1; 151 } 152 if (q.curNode->rchild != NULL) 153 { 154 Q[++rear].curNode = q.curNode->rchild; 155 Q[rear].level = q.level + 1; 156 } 157 } 158 }
main.cpp
1 #include<iostream> 2 using namespace std; 3 #include"BiTree.cpp" 4 int main() { 5 BiTree<char> tree; 6 cout << "前序遍历为:"; 7 tree.PreOrder(); 8 cout << endl; 9 cout << "中序遍历为:"; 10 tree.InOrder(); 11 cout << endl; 12 cout << "后序遍历为:"; 13 tree.PostOrder(); 14 cout << endl; 15 cout << "层序遍历为:"; 16 tree.LeverOrder(); 17 cout << endl; 18 cout << "层序(带层数)遍历为:"<<endl; 19 tree.LeverOrderh(); 20 cout << endl; 21 system("pause"); 22 return 0; 23 }