数据结构之栈
一、栈的特点
(1)栈是一种线性结构,栈中的元素遵循先入后出的原则,最先进入的元素所在位置叫做栈底,最后放入的元素所在位置叫做栈顶。
这种结构类似于盛放羽毛球的圆筒,一端封闭,另一端开口,先放入的羽毛球位于筒的底部(即栈底),后放入的羽毛球位于筒的入口(即栈顶)。
(2)栈也是一种抽象的逻辑结构,依赖于物理结构(如数组、链表)而存在。既可以使用数组实现,也可以使用链表实现。
(3)出栈、入栈的时间复杂都是O(1)。
二、 栈的基本操作
栈的基本操作主要是出栈、入栈、获取栈顶元素等。
(1)入栈
栈的入栈操作只允许从栈顶一侧放入新元素,放入的新元素成为新的栈顶。
(2) 出栈
栈的出栈操作只允许从栈顶弹出,出栈元素的前一个元素变成了新的栈顶。
三、基于数组实现栈
1 #include <iostream> 2 #include <assert.h> 3 4 // 基于数组实现的栈(模板类) 5 template <class T> 6 class ArrayStack 7 { 8 public : 9 ArrayStack(int nCapcity = 8); 10 ~ArrayStack(); 11 12 bool Push(const T& ele); 13 T Pop(); 14 T& GetPop(); 15 int GetNum(); 16 17 private: 18 void Resize(); 19 private: 20 T* m_pElement; 21 int m_nCapicity; 22 int m_nNum; 23 }; 24 25 template<class T> 26 ArrayStack<T>::ArrayStack(int nCapcity) 27 :m_nCapicity(nCapcity) 28 ,m_pElement(new T[nCapcity]) 29 ,m_nNum(0) 30 { 31 32 } 33 34 template<class T> 35 ArrayStack<T>::~ArrayStack() 36 { 37 delete[] m_pElement; 38 } 39 40 template<class T> 41 bool ArrayStack<T>::Push(const T& ele) 42 { 43 if(m_pElement == NULL) 44 { 45 printf(" m_pElement == NUL \n"); 46 assert(false && "m_pElement == NUL"); 47 return false; 48 } 49 if(m_nNum >= m_nCapicity) 50 { 51 Resize(); 52 } 53 54 m_pElement[m_nNum] = ele; 55 m_nNum++; 56 return true; 57 } 58 59 template<class T> 60 T ArrayStack<T>::Pop() 61 { 62 if(m_nNum <= 0) 63 { 64 return NULL; 65 } 66 67 m_nNum--; 68 return m_pElement[m_nNum]; 69 } 70 71 template<class T> 72 T& ArrayStack<T>::GetPop() 73 { 74 if(m_nNum <= 0) 75 { 76 return NULL; 77 } 78 79 return m_pElement[m_nNum - 1]; 80 } 81 82 template<class T> 83 int ArrayStack<T>::GetNum() 84 { 85 return m_nNum; 86 } 87 88 template<class T> 89 void ArrayStack<T>::Resize() 90 { 91 if(NULL == m_pElement) 92 { 93 if(m_nCapicity == 0) 94 { 95 m_nCapicity = 8; 96 } 97 m_pElement = new T[m_nCapicity]; 98 return; 99 } 100 101 T* pNewEle = new T[m_nCapicity * 2]; 102 for(int i = 0;i < m_nNum;i++) 103 { 104 pNewEle[i] = m_pElement[i]; 105 } 106 107 delete[] m_pElement; 108 m_pElement = pNewEle; 109 m_nCapicity = m_nCapicity * 2; 110 } 111 112 int main() 113 { 114 printf("Welcome to stack! \n"); 115 116 ArrayStack<int> stackVal1(4); 117 stackVal1.Push(1); 118 stackVal1.Push(10); 119 stackVal1.Push(20); 120 stackVal1.Push(40); 121 stackVal1.Push(60); 122 123 int nNum = stackVal1.GetNum(); 124 printf("------num:%d \n",nNum); 125 126 for(int i = 0;i < nNum;i++) 127 { 128 int val1 = stackVal1.Pop(); 129 printf("%d ",val1); 130 } 131 printf("\n"); 132 133 nNum = stackVal1.GetNum(); 134 printf("------num:%d \n",nNum); 135 return 0; 136 }
四、基于链表实现栈
1 #include <iostream> 2 #include <assert.h> 3 4 template<class T> 5 class Node 6 { 7 public: 8 Node():m_pNext(NULL){} 9 Node(T& data):m_Data(data),m_pNext(NULL){} 10 Node(T& data,Node<T>* pNext):m_Data(data),m_pNext(pNext){} 11 public: 12 T m_Data; 13 Node<T>* m_pNext; 14 }; 15 16 //单链表 17 template<class T> 18 class SingleList 19 { 20 public: 21 SingleList():m_pHead(NULL),m_pCurrent(NULL),m_nSize(0){} 22 ~SingleList() 23 { 24 Clear(); 25 } 26 27 //获取链表元素个数 28 int GetNum() 29 { 30 return m_nSize; 31 } 32 33 //尾部插入新节点 34 bool InsertNode(const T& data) 35 { 36 Node<T>* pNew = new Node<T>(); 37 pNew->m_Data = data; 38 pNew->m_pNext = NULL; 39 if(m_pHead == NULL) 40 { 41 m_pHead = pNew; 42 m_pCurrent = pNew; 43 } 44 else 45 { 46 m_pCurrent->m_pNext = pNew; 47 m_pCurrent = pNew; 48 } 49 m_nSize++; 50 return true; 51 } 52 53 //删除节点 54 int DeleteNode() 55 { 56 if(m_nSize == 0 || m_pHead == NULL|| NULL == m_pCurrent) 57 { 58 return -1; 59 } 60 61 if(m_pHead == m_pCurrent) 62 { 63 m_pHead = m_pCurrent->m_pNext; 64 delete m_pCurrent; 65 m_pCurrent = m_pHead; 66 } 67 else 68 { 69 Node<T>* pCurrent = m_pHead; 70 while(pCurrent) 71 { 72 if(pCurrent->m_pNext == m_pCurrent) 73 { 74 pCurrent->m_pNext = m_pCurrent->m_pNext; 75 delete m_pCurrent; 76 m_pCurrent = pCurrent; 77 break; 78 } 79 else 80 { 81 pCurrent = pCurrent->m_pNext; 82 } 83 } 84 } 85 86 m_nSize--; 87 return m_nSize; 88 } 89 90 //获取当前节点数据 91 void GetCurrentNodeData(T& data) 92 { 93 if(m_pCurrent) 94 { 95 data = m_pCurrent->m_Data ; 96 } 97 } 98 99 //设置当前节点数据 100 void SetCurrentNodeData(T& data) 101 { 102 if(m_pCurrent) 103 { 104 m_pCurrent->m_Data = data; 105 } 106 } 107 108 //清空列表 109 void Clear() 110 { 111 if(m_nSize == 0 || m_pHead == NULL) 112 { 113 return; 114 } 115 116 Node<T>* tepCurrent = m_pHead; 117 Node<T>* tepNext = m_pHead->m_pNext; 118 119 while(tepCurrent) 120 { 121 delete tepCurrent; 122 tepCurrent = tepNext; 123 if(tepNext) 124 { 125 tepNext = tepNext->m_pNext; 126 } 127 } 128 m_pHead = NULL; 129 m_pCurrent = NULL; 130 m_nSize = 0; 131 } 132 private: 133 Node<T>* m_pHead; 134 Node<T>* m_pCurrent; 135 int m_nSize; 136 }; 137 138 template<class T> 139 class LinkStack 140 { 141 public: 142 LinkStack(){} 143 ~LinkStack(){} 144 //获取元素个数 145 int GetNum() 146 { 147 return m_SingleList.GetNum(); 148 } 149 150 //添加新元素 151 bool Push(const T& data) 152 { 153 return m_SingleList.InsertNode(data); 154 } 155 156 //移除栈顶元素 157 T Pop() 158 { 159 T temp; 160 if(GetNum() <= 0) 161 { 162 return -1; 163 } 164 m_SingleList.GetCurrentNodeData(temp); 165 m_SingleList.DeleteNode(); 166 return temp; 167 } 168 private: 169 SingleList<T> m_SingleList; 170 }; 171 172 int main() 173 { 174 printf("Welcome to link stack.\n"); 175 LinkStack<int> stackVal2; 176 stackVal2.Push(100); 177 stackVal2.Push(200); 178 stackVal2.Push(300); 179 stackVal2.Push(500); 180 181 int nNum = stackVal2.GetNum(); 182 for(int i = 0;i < nNum;i++) 183 { 184 int val = stackVal2.Pop(); 185 printf("Pop:%d =================\n",val); 186 } 187 188 189 return 0; 190 }