概要
线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列。线性表的几个基本组成部分:数组、单向链表、双向链表。
一、数组
数组有上界和下界,数组的元素在上下界内是连续的。
数组的特点是:数据是连续的;随机访问速度快。
数组中稍微复杂一点的是多维数组和动态数组。
二、单向链表
定义:
单向链表(单链表)时链表的一种,它由节点组成,每个节点都包含下一个节点的指针。
单链表的特点是:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。
实现:
单链表的实现方式有很多种,常见的有
(1)带头结点的单链表
(2)不带头结点的单链表
(3)带头节点和尾节点的单链表
(1)和(2)的主要区别是:(1)的头节点是个空节点,其主要作用是指向链表的第一个节点,(2)的头结点不是空节点,是整个链表的第一个节点。(3)是一个循环链表,即链表的尾节点指向头结点;下面会对各种实现方式进行具体的介绍。
C++实现单链表(带头结点)
SList.h
1 typedef int Type; 2 //定义节点类 3 struct Node 4 { 5 Node(const Type x); 6 Type data; 7 Node *next; 8 }; 9 10 class SList 11 { 12 public: 13 SList();//构造函数 14 SList(const SList&s);//拷贝构造函数 15 SList &operator=(SList &s);//赋值运算符重载 16 ~SList();//析构函数 17 18 public: 19 //单链表的具体操作 20 bool isEmpty(); 21 int length(); 22 void reverseList();//逆置 23 void printList();//打印链表 24 void Clear(); 25 //void sortList();//排序 26 void pushBack(const Type &data);//在尾部插入一个节点 27 void popBack();//删除尾节点 28 void pushFront(Type data);//头插 29 void popFront();//删除头节点 30 31 private: 32 Node *head; 33 int len;//链表长度 34 };
SList.cpp
1 #include <iostream> 2 #include "SList.h" 3 4 using namespace std; 5 //节点类的构造函数 6 Node::Node(const Type x) 7 :data(x),next(NULL) 8 { 9 10 } 11 //构造函数 12 SList::SList() 13 :head(NULL),len(0) 14 { 15 head = new Node(NULL); 16 head->next = NULL; 17 } 18 //拷贝构造函数 19 SList::SList(const SList &s) 20 { 21 head->next = NULL; 22 len = s.len; 23 Node *current; //自己链表的尾部元素 24 Node *sCurrent = s.head->next;//s的第一个元素 25 while(sCurrent != NULL) 26 { 27 for(int i = 1; i <= s.len; i++) 28 { 29 Node *newNode = new Node(sCurrent->data); 30 31 if(i == 1) 32 { 33 head->next = newNode; 34 current = head->next; 35 } 36 else 37 { 38 current->next = newNode; 39 current = current->next; 40 } 41 sCurrent = sCurrent->next; 42 } 43 } 44 } 45 //赋值运算符重载 46 SList& SList::operator=(SList &s)//推荐写法 47 { 48 if(this != &s) 49 { 50 swap(head, s.head); 51 } 52 return *this; 53 } 54 55 //析构函数 56 SList::~SList() 57 { 58 Clear(); 59 } 60 //清空链表 61 void SList::Clear() 62 { 63 Node *current = NULL; 64 Node *p = head->next; 65 while(p != NULL) 66 { 67 current = p->next; 68 delete p; 69 p = current; 70 } 71 delete current; 72 current = NULL; 73 74 delete head; 75 p = NULL; 76 len = 0; 77 } 78 79 //链表尾部插入 80 void SList::pushBack(const Type &data) 81 { 82 if(head->next == NULL) 83 { 84 head->next = new Node(data); 85 len++; 86 } 87 else 88 { 89 Node *p = head->next; 90 while(p->next != NULL) 91 { 92 p = p->next; 93 } 94 p->next = new Node(data); 95 len++; 96 97 p = NULL; 98 } 99 } 100 //链表尾部删除 101 void SList::popBack() 102 { 103 if(head->next == NULL) 104 cout << "this SList is empty." << endl; 105 else 106 { 107 Node *current; 108 Node *p = head->next; 109 for(int i = 1; i < len-1; i++) 110 { 111 p = p->next; 112 } 113 current = p->next; 114 p->next = current->next; 115 delete current; 116 current = NULL; 117 len--; 118 } 119 } 120 void SList::printList() 121 { 122 if(head->next == NULL) 123 cout << "this SList is empty." << endl; 124 else 125 { 126 Node *temp = head->next; 127 while(temp != NULL) 128 { 129 cout << temp->data << " "; 130 temp = temp->next; 131 } 132 cout << endl; 133 delete temp; 134 temp = NULL; 135 } 136 } 137 138 //判断链表是否为空 139 bool SList::isEmpty() 140 { 141 if(head->next == NULL) 142 return true; 143 else 144 return false; 145 } 146 147 //获取链表长度 148 int SList::length() 149 { 150 return len; 151 } 152 153 //链表逆置 154 void SList::reverseList() 155 { 156 Node *temp = head->next; 157 head->next = NULL; 158 if(temp == NULL) 159 cout << "this SList is empty." << endl; 160 else 161 { 162 while(temp != NULL) 163 { 164 Node *p = temp->next; 165 temp->next = head->next; 166 head->next = temp; 167 temp = p; 168 } 169 } 170 } 171 172 void SList::pushFront(Type data) 173 { 174 if(head->next == NULL) 175 head->next = new Node(data); 176 else 177 { 178 Node *temp = new Node(data); 179 temp->next = head->next; 180 head->next = temp; 181 } 182 } 183 184 void SList::popFront() 185 { 186 if(head->next == NULL) 187 cout << "this SList is empty." << endl; 188 else 189 { 190 Node *temp = head->next; 191 head->next = temp->next; 192 delete temp; 193 } 194 }
main.cpp
1 #include <iostream> 2 #include "SList.h" 3 4 using namespace std; 5 6 int main() 7 { 8 SList mylist; 9 10 mylist.pushBack(1); 11 mylist.pushBack(2); 12 mylist.pushBack(3); 13 mylist.printList(); 14 15 mylist.popBack(); 16 mylist.printList(); 17 18 mylist.reverseList(); 19 mylist.printList(); 20 21 mylist.pushFront(5); 22 mylist.printList(); 23 24 mylist.popFront(); 25 mylist.printList(); 26 return 0; 27 }
C++实现单链表(不带头结点)
SList.h
1 typedef int Type; 2 //定义节点类 3 struct Node 4 { 5 Node(const Type x); 6 Type data; 7 Node *next; 8 }; 9 10 class SList 11 { 12 public: 13 SList();//构造函数 14 SList(const SList&s);//拷贝构造函数 15 SList &operator=(SList &s);//赋值运算符重载 16 ~SList();//析构函数 17 18 public: 19 //单链表的具体操作 20 bool isEmpty(); 21 int length(); 22 void reverseList();//逆置 23 void printList();//打印链表 24 void Clear(); 25 //void sortList();//排序 26 void pushBack(const Type &data);//在尾部插入一个节点 27 void popBack();//删除尾节点 28 void pushFront(Type data);//头插 29 void popFront();//删除头节点 30 31 private: 32 Node *head; 33 int len;//链表长度 34 };
SList.cpp
1 #include <iostream> 2 #include <assert.h> 3 #include "SList.h" 4 5 using namespace std; 6 //节点类的构造函数 7 Node::Node(const Type x) 8 :data(x),next(NULL) 9 { 10 11 } 12 //构造函数 13 SList::SList() 14 :head(NULL),len(0) 15 { 16 17 } 18 //拷贝构造函数 19 SList::SList(const SList &s) 20 { 21 head = NULL; 22 len = s.len; 23 Node *current; //自己链表的尾部元素 24 Node *sCurrent = s.head;//s的第一个元素 25 while(sCurrent != NULL) 26 { 27 for(int i = 1; i < s.len; i++) 28 { 29 Node *newNode = new Node(NULL); 30 newNode->data = sCurrent->data; 31 newNode->next = NULL; 32 if(i ==1) 33 { 34 head = newNode; 35 current = head; 36 } 37 else 38 { 39 current->next = newNode; 40 current = current->next; 41 } 42 sCurrent = sCurrent->next; 43 } 44 } 45 } 46 //赋值运算符重载 47 SList& SList::operator=(SList &s)//赋值运算符重载() 48 { 49 if(this != &s) 50 { 51 swap(head, s.head); 52 } 53 return *this; 54 } 55 56 //析构函数 57 SList::~SList() 58 { 59 Clear(); 60 } 61 //清空链表 62 void SList::Clear() 63 { 64 Node *current; 65 while(head != NULL) 66 { 67 current = head; 68 head = current->next; 69 delete current; 70 } 71 head = NULL; 72 len = 0; 73 } 74 //尾部插入新节点 75 void SList::pushBack(const Type &data) 76 { 77 if(head == NULL) 78 { 79 head = new Node(data); 80 len++; 81 } 82 else 83 { 84 Node *p = head; 85 while(p->next != NULL) 86 { 87 p = p->next; 88 } 89 p->next = new Node(data); 90 len++; 91 92 p = NULL; 93 } 94 } 95 //打印链表 96 void SList::printList() 97 { 98 if(head == NULL) 99 { 100 cout << "this SList is empty ! " << endl; 101 return ; 102 } 103 else 104 { 105 Node *temp = head; 106 while(temp != NULL) 107 { 108 cout << temp->data << " "; 109 temp = temp->next; 110 } 111 cout << endl; 112 } 113 } 114 //判断链表是否空 115 bool SList::isEmpty() 116 { 117 if(head == NULL) 118 return true; 119 else 120 return false; 121 } 122 //获取链表长度 123 int SList::length() 124 { 125 return len; 126 } 127 //头插法逆置矩阵 128 void SList::reverseList() 129 { 130 Node *current = head; 131 head = NULL; 132 if(current == NULL) 133 { 134 cout << "this SList is empty." << endl; 135 } 136 else 137 { 138 while(current != NULL) 139 { 140 Node *nextCurrent = current->next; 141 //头插法链表逆置 142 current->next = head;//head = NULL 143 head = current; 144 current = nextCurrent; 145 } 146 } 147 } 148 //删除尾节点 149 void SList::popBack() 150 { 151 if(head == NULL) 152 cout << "this SList is empty." << endl; 153 else 154 { 155 Node *p = head; 156 //找到倒数第二个节点 157 for(int i = 1; i < len-1; i++) 158 { 159 p = p->next; 160 } 161 Node *current = p->next; 162 p->next = current->next; 163 delete current; 164 len--; 165 } 166 } 167 168 //头部插入 169 void SList::pushFront(Type Data) 170 { 171 if(head == NULL) 172 { 173 pushBack(Data); 174 } 175 else 176 { 177 Node *temp = head; 178 head = new Node(Data); 179 head->next = temp; 180 } 181 } 182 183 //头部删除 184 void SList::popFront() 185 { 186 if(head == NULL) 187 cout << "this SList is empty." << endl; 188 else 189 { 190 Node *temp = head; 191 head = temp->next; 192 delete temp; 193 } 194 }
main.cpp
1 #include <iostream> 2 #include "SList.h" 3 4 using namespace std; 5 6 int main() 7 { 8 SList myList; 9 myList.pushBack(1); 10 myList.pushBack(2); 11 myList.pushBack(3); 12 myList.printList(); 13 14 myList.reverseList(); 15 myList.printList(); 16 17 myList.popBack(); 18 myList.printList(); 19 20 myList.pushFront(4); 21 myList.printList(); 22 23 myList.popFront(); 24 myList.printList(); 25 return 0; 26 }
C++实现单链表(带头结点和尾结点)
SList.h
1 typedef int Type; 2 //定义节点类 3 struct Node 4 { 5 Node(const Type x); 6 Type data; 7 Node *next; 8 }; 9 10 class SList 11 { 12 public: 13 SList();//构造函数 14 SList(const SList&s);//拷贝构造函数 15 SList &operator=(SList &s);//赋值运算符重载 16 ~SList();//析构函数 17 18 public: 19 //单链表的具体操作 20 bool isEmpty(); 21 int length(); 22 void reverseList();//逆置 23 void printList();//打印链表 24 void Clear(); 25 //void sortList();//排序 26 void pushBack(const Type &data);//在尾部插入一个节点 27 void popBack();//删除尾节点 28 void pushFront(Type data);//头插 29 void popFront();//删除头节点 30 31 private: 32 Node *head; 33 Node *tail; 34 int len;//链表长度 35 };
SList.cpp
1 #include <iostream> 2 #include <assert.h> 3 #include "SList.h" 4 5 using namespace std; 6 //节点类的构造函数 7 Node::Node(const Type x) 8 :data(x),next(NULL) 9 { 10 11 } 12 //构造函数 13 SList::SList() 14 :head(NULL),tail(NULL),len(0) 15 { 16 17 } 18 //拷贝构造函数 19 SList::SList(const SList &s) 20 { 21 if(s.head == NULL) 22 return; 23 Node *temp = s.head; 24 do{ 25 pushBack(temp->data); 26 temp = temp->next; 27 }while(temp != s.head); 28 len = s.len; 29 } 30 //赋值运算符重载 31 SList& SList::operator=(SList &s)//赋值运算符重载() 32 { 33 if(this != &s) 34 { 35 swap(head, s.head); 36 swap(tail, s.tail); 37 } 38 return *this; 39 } 40 41 //析构函数 42 SList::~SList() 43 { 44 Clear(); 45 } 46 //清空链表 47 void SList::Clear() 48 { 49 Node *current = head; 50 while(current != tail) 51 { 52 head = head->next; 53 delete current; 54 current = head; 55 } 56 head = NULL; 57 tail = NULL; 58 len = 0; 59 } 60 //尾部插入新节点 61 void SList::pushBack(const Type &data) 62 { 63 if(head == NULL) 64 { 65 head = new Node(data); 66 tail = head; 67 tail->next = head; 68 } 69 else 70 { 71 tail->next = new Node(data); 72 tail = tail->next; 73 tail->next = head; 74 } 75 len++; 76 } 77 //打印链表 78 void SList::printList() 79 { 80 if(head == NULL) 81 { 82 cout << "this SList is empty ! " << endl; 83 return ; 84 } 85 else 86 { 87 Node *temp = head; 88 do{ 89 cout << temp->data << " "; 90 temp = temp->next; 91 }while(temp != head); 92 cout << endl; 93 } 94 } 95 //判断链表是否空 96 bool SList::isEmpty() 97 { 98 if(head == NULL) 99 return true; 100 else 101 return false; 102 } 103 //获取链表长度 104 int SList::length() 105 { 106 return len; 107 } 108 //头插法逆置矩阵 109 void SList::reverseList() 110 { 111 if(head == NULL || head->next == tail) 112 { 113 return ; 114 } 115 tail = new Node(head->data); 116 Node *begin = NULL; 117 Node *temp = tail; 118 while(len--) 119 { 120 Node *del = head; 121 head = head->next; 122 delete del; 123 begin = new Node(head->data); 124 begin->next = temp; 125 tail->next = begin; 126 temp = begin; 127 } 128 head = begin; 129 } 130 //删除尾节点 131 void SList::popBack() 132 { 133 if(head == NULL) 134 cout << "this SList is empty." << endl; 135 else if(head == tail) 136 { 137 delete head; 138 head = NULL; 139 tail = NULL; 140 } 141 else 142 { 143 Node *current = head; 144 while(current->next != tail) 145 { 146 current = current->next; 147 } 148 delete tail; 149 tail = current; 150 tail->next = head; 151 } 152 } 153 154 //头部插入 155 void SList::pushFront(Type Data) 156 { 157 if(head == NULL) 158 { 159 pushBack(Data); 160 } 161 else 162 { 163 Node *temp = head; 164 head = new Node(Data); 165 head->next = temp; 166 tail->next = head; 167 } 168 } 169 170 //头部删除 171 void SList::popFront() 172 { 173 if(head == NULL) 174 { 175 cout << "this SList is empty." << endl; 176 return ; 177 } 178 else 179 { 180 Node *temp = head; 181 head = head->next; 182 tail->next = head; 183 delete temp; 184 } 185 }
main.cpp
1 #include <iostream> 2 #include "SList.h" 3 4 using namespace std; 5 6 int main() 7 { 8 SList myList; 9 myList.pushBack(1); 10 myList.pushBack(2); 11 myList.pushBack(3); 12 myList.printList(); 13 14 myList.reverseList(); 15 myList.printList(); 16 17 myList.popBack(); 18 myList.printList(); 19 20 myList.pushFront(4); 21 myList.printList(); 22 23 myList.popFront(); 24 myList.printList(); 25 return 0; 26 }
三、双向链表
双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
DList.h
1 typedef int DataType; 2 3 struct DNode 4 { 5 DataType data; 6 DNode *prev; 7 DNode *next; 8 DNode(const DataType x); 9 }; 10 11 class DList 12 { 13 public: 14 DList();//构造函数 15 DList(const DList &s);//拷贝构造函数 16 DList &operator=(DList &s);//赋值运算符重载 17 ~DList();//析构函数 18 19 public: 20 void reverseList(); 21 void printList(); 22 void pushBack(DataType x); 23 void popBack(); 24 void pushFront(DataType x); 25 void popFront(); 26 //void removeNode(DataType x); 27 void Clear(); 28 int getLength(); 29 30 private: 31 DNode *head;//指向头结点 32 DNode *tail;//指向尾结点 33 int len; 34 };
DList.cpp
1 #include <iostream> 2 #include <assert.h> 3 #include "DList.h" 4 5 using namespace std; 6 //结点构造函数 7 DNode::DNode(const DataType x) 8 :data(x), prev(NULL), next(NULL) 9 { 10 11 } 12 //构造函数 13 DList::DList() 14 :len(0), head(NULL), tail(NULL) 15 {} 16 17 //拷贝构造函数 18 DList::DList(const DList &s) 19 :len(0), head(NULL), tail(NULL) 20 { 21 len = s.len; 22 if(s.head == NULL) 23 return; 24 DNode *temp = s.head; 25 while(temp) 26 { 27 pushBack(temp->data); 28 temp = temp->next; 29 } 30 } 31 32 //赋值运算符重载(推荐写法),其本质上是与拷贝构造函数的工作是一样的 33 DList &DList::operator=(DList &s) 34 { 35 if(this != &s) 36 { 37 swap(head, s.head); 38 swap(tail, s.tail); 39 len = s.len; 40 } 41 return *this; 42 } 43 44 DList::~DList() 45 { 46 Clear(); 47 } 48 49 void DList::Clear() 50 { 51 DNode *temp = head; 52 while(temp != tail) 53 { 54 head = head->next; 55 delete temp; 56 temp = head; 57 } 58 head = NULL; 59 tail = NULL; 60 len = 0; 61 } 62 //尾部插入新结点 63 void DList::pushBack(DataType x) 64 { 65 if(head == NULL) 66 { 67 head = new DNode(x); 68 tail = head; 69 len++; 70 } 71 else 72 { 73 tail->next = new DNode(x); 74 tail->next->prev = tail; 75 tail = tail->next; 76 len++; 77 } 78 } 79 80 //尾部删除一个结点 81 void DList::popBack() 82 { 83 if(head == NULL) 84 { 85 cout << "this DList is empty." << endl; 86 return; 87 } 88 else if(head == tail) 89 { 90 delete head; 91 head = NULL; 92 tail = NULL; 93 len = 0; 94 } 95 else 96 { 97 DNode *temp = head; 98 while(temp->next != tail) 99 { 100 temp = temp->next; 101 } 102 delete tail; 103 tail = temp; 104 tail->prev = temp->prev; 105 tail->next = NULL; 106 len--; 107 } 108 } 109 110 //头部插入一个新节点 111 void DList::pushFront(DataType x) 112 { 113 if(head == NULL) 114 { 115 pushBack(x); 116 len++; 117 } 118 else 119 { 120 DNode *temp = head; 121 head = new DNode(x); 122 head->next = temp; 123 temp->prev = head; 124 len++; 125 } 126 } 127 128 //头部删除一个结点 129 void DList::popFront() 130 { 131 if(head == NULL) 132 { 133 cout << "this DList is empty." << endl; 134 return; 135 } 136 else if(head == tail) 137 { 138 delete head; 139 head = NULL; 140 tail = NULL; 141 len = 0; 142 } 143 else 144 { 145 DNode *temp = head->next; 146 delete head; 147 head = temp; 148 head->next = temp->next; 149 temp->next->prev = head; 150 len--; 151 } 152 } 153 154 int DList::getLength() 155 { 156 return len; 157 } 158 159 void DList::reverseList() 160 { 161 if(head == NULL || head == tail) 162 { 163 return; 164 } 165 //头插法逆置双链表 166 tail = new DNode(head->data); 167 DNode *begin = NULL; 168 DNode *temp = tail; 169 while(--len) 170 { 171 DNode *del = head; 172 head = head->next; 173 delete del; 174 begin = new DNode(head->data); 175 begin->next = temp; 176 temp->prev = begin; 177 temp = begin; 178 } 179 head = begin; 180 } 181 182 void DList::printList() 183 { 184 if(head == NULL) 185 { 186 cout << "this DList is empty." << endl; 187 return ; 188 } 189 else 190 { 191 DNode *temp = head; 192 while(temp != NULL) 193 { 194 cout << temp->data << " "; 195 temp = temp->next; 196 } 197 cout << endl; 198 } 199 }
main.cpp
1 #include <iostream> 2 #include "DList.h" 3 4 using namespace std; 5 6 int main() 7 { 8 DList myDList; 9 myDList.pushBack(1); 10 myDList.pushBack(2); 11 myDList.pushBack(3); 12 myDList.pushBack(4); 13 myDList.printList(); 14 15 cout << "链表长度len = " << myDList.getLength() << endl; 16 17 myDList.reverseList(); 18 myDList.printList(); 19 20 myDList.pushFront(1); 21 myDList.printList(); 22 23 return 0; 24 }