# 线性表 (Linear List)定义
零个或多个数据元素的有限序列
存储结构和存取结构
存储结构是数据及其逻辑结构在内存中的表示 存取结构是一个数据结构对查找操作的时间性能的一种描述1 2 3 4 5 6 7 8 graph LR; StorageStructure("存储结构(Storage Structure)")-->SequentialStorageStructure("顺序存储结构(Sequential Storage Structure)") StorageStructure-->LinkedStorageStructure("链式存储结构(Linked Storage Structure))") StorageStructure-->IndexedStorageStructure("索引存储结构(Indexed Storage Structure)") StorageStructure-->HashStorageStructure("散列存储结构(Hash Storage Structure)") AccessMethod("存取方式(Access Method)")--> SequentialAccess("顺序存取(Sequential Access)") AccessMethod-->RandomAccess("随机存取(Random Access)")
# 1. 顺序表 (Sequential List)# 1.1 定义一段地址连续的存储单元依次存储线性表的数据元
# 1.2 存储结构和存取结构顺序表是一种随机存取的顺序存储结构
# 1.3 使用场景# 1.4 顺序表代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 #include <iostream> using namespace std;const int MAX_SIZE=100 ;template <class T >class SeqList {private : T data[MAX_SIZE]; int length; public : SeqList ():length (0 ){} SeqList (const T arr[],const int len); int length () const ; T searchByIndex (const int index) const ; int searchByValue (const T value) const ; bool insert (const int index,const T value) ; bool removeByIndex (const int index) ; bool removeByValue (const T value) ; void printSeqList () const ; } template <class T >SeqList<T>::SeqList<const T arr[],const int len){ if (len >MAX_SIZE){ cerr<<"Insufficient LIST" ; exit (1 ); } length=len; for (int i=0 ;i<len;i++){ data[i]=arr[i]; } } template <class T >int SeqList<T>::length () const { return length; } template <class T >T SeqList<T>::searchByIndex (const int index) const { if (index<1 ||index>length){ cerr<<"Illegal Search Index" ; exit (1 ); } return data[index-1 ]; } template <class T >int SeqList<T>::searchByValue (const T value) const { for (int i=0 ;i<length;i++){ if (data[i]==value){ return i+1 ; } } return -1 ; } template <class T >bool SeqList<T>::insert (const int index,const T value){ if (length>=MAX_SIZE){ cerr<<"Array Overflow" ; return false ; } if (index<1 ||index>length+1 ){ cerr<<"Illegal Insert Position" ; return false ; } for (int i=length-1 ;i>=index-1 ;i--){ data[i+1 ]=data[i]; } data[index-1 ]=value; length++; return true ; } template <class T >bool SeqList<T>::removeByIndex (const int index){ if (length==0 ){ cerr<<"Array Out of Bounds" ; return false ; } if (index<1 ||index>length){ cerr<<"Illegal Remove Position" ; return false ; } for (int i=index;i<length;i++){ data[i-1 ]=data[i]; } length--; return true ; } template <class T >bool SeqList<T>::removeByValue (const T value){ int index=-1 ; for (int i=0 ;i<length;i++){ if (data[i]==value){ index=i; break ; } } if (index!=-1 ){ for (int i=index+1 ;i<length;i++){ data[i-1 ]=data[i]; } length--; return true ; } return false ; } template <class T >void SeqList<T>::printSeqList () const { for (int i=0 ;i<length;i++){ cout<<data[i]<<"\t" ; } cout<<endl; }
# 2. 链表# 2.1 定义一个或多个结点 组合而成的数据结构称为链表
# 2.2 结点结点一般由数据域 和指针域 构成
# 2.3 头指针和头结点** 头结点的数据域可以不存储任何信息,其指针域指向头指针 **
头指针:链表的第一个结点 头结点:在头指针前附设一个结点 为什么有时候头结点不必须存在呢?
空链表情况:当链表为空时,头结点可以省略,直接用头指针为 null 或者指向第一个实际节点。 操作方便性:有时在操作链表时,不需要头结点,直接用头指针指向第一个节点即可。 节省空间:省略头结点可以节省一个节点的空间,在链表数据量较大时可能会显著节省空间。 # 2.4 存储结构和存取结构单链表是一种顺序存取的链式存储结构
# 2.4 使用场景# 2.5 常用链表# 2.5.1 单向链表代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 #include <iostream> using namespace std;template <class T >struct Node { T data; Node<T>* next; Node (T value):data (value),next (nullptr ){} }; template <class T >class LinkList {private : Node<T>* head; public : LinkList (); LinkList (const T arr[],const int len); ~LinkList (); int length () const ; T searchByIndex (const int index) const ; int searchByValue (const T value) const ; bool insert (const int index, const T value) ; bool removeByIndex (const int index) ; bool removeByValue (const T value) ; void printLinkList () const ; } template <class T >LinkList<T>::LinkList (){ head= new Node<T>; head->next= nullptr ; } template <class T >LinkList<T>::LinkList (const T arr[],const int len){ head=new Node<T>; Node<T>* rear=head; for (int i=0 ;i<len;i++){ Node<T>* s=new Node <T>(arr[i]); rear->next=s; rear=s; } rear->next=nullptr ; } template <class T >LinkList<T>::~LinkList (){ Node<T>* current=head; while (current){ Node<T>* temp=current; current=current->next; delete temp; } head=nullptr ; } template <class T >int LinkList<T>::length ()const { Node<T> *cur=head->next; int len=0 ; while (cur){ cur=cur->next; len++; } return len; } template <class T >T LinkList<T>::searchByIndex (const int index)const { Node<T>* cur=head->next; int j=1 ; while (cur&&j<index){ cur=cur->next; j++; } if (!cur||j>index){ cerr<<"Illegal Search Index" ; exit (1 ); } else { return cur->data; } } template <class T >int LinkList<T>::searchByValue (const T value)const { Node<T>* cur=head->next; int j=1 ; while (cur&&cur->data!=value){ cur=cur->next; j++; } if (cur){ return j; } else { return -1 ; } } template <class T >bool LinkList<T>::insert (const int index,const T value){ Node<T>* cur=head; int j=0 ; while (cur&&j<index-1 ){ cur=cur->next; j++; } if (!cur||j>i-1 ){ cerr<<"Illegal Insert Position" ; return false ; } else { Node<T>* temp=new Node <T>(value); temp->next=cur->next; cur->next=temp; return true ; } } template <class T >bool LinkList<T>::removeByIndeX (const int index){ Node<T>* cur=head; int j=0 ; while (cur&&j<index-1 ){ cur=cur->next; j++; } if (!cur||!cur->next){ cerr<<"Illegal Delete Position" ; return false ; } else { Node<T>* temp=cur->next; cur->next=temp->next; delete temp; return true ; } } template <class T >bool LinkList<T>::removeByValue (const T value){ Node<T>* cur=head; while (cur&&cur->data!=value){ cur=cur->next; } if (!cur||!cur->next){ cerr<<"Illegal Delete Position" ; return false ; } else { Node<T>* temp=cur->next; cur->next=temp->next; delete temp; return true ; } } template <class T >void LinkList<T>::printLinkList ()const { Node<T>*cur=head-next; while (cur){ cout<<cur->data<<"\t" ; cur=cur-next; } }
# 2.5.2 循环链表由于循环链表循环判断为cur->next=head,因此可以不采用头结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 #include <iostream> using namespace std;template <class T >struct Node { T data; Node<T>* next; Node (T value):data (value),next (nullptr ){} }; template <class T >class CircularLinkList {private : Node<T>* head; Node<T>* tail; public : CircularLinkList (); CircularLinkList (const T arr[],const int len); ~CircularLinkList (); int length () const ; bool insertByFront (const T value) ; bool insertByRear (const T value) ; bool searchByValue (const T value) const ; void printCircularLinkList () const ; } template <class T >CircularLinkList<T>::CircularLinkList (){ head=new Node<T>; head->next=head; tail=head; } template <class T >CircularLinkList<T>::CircularLinkList (const T arr[],const int len){ for (int i=0 ;i<len;i++){ insertByRear (arr[i]); } } template <class T >CircularLinkList<T>::~CircularLinkList (){ Node<T>* cur=head; while (cur){ Node<T>* temp=cur; crur=cur->next; delete temp; } head=nullptr ; tail=nullptr ; } template <class T >int CircularLinkList<T>::length ()const { if (!head) return 0 ; int len=0 ; Node<T>* cur=head; while (cur->next!=head){ cur=cur->next; len++; } return len; } template <class T >bool CircularLinkList<T>::insertByFront (const T value){ Node<T>* temp=new Node <T>(value); if (!head){ head=temp; tail=temp; temp->next=temp; } else { temp->next=head; tail->next=temp; head=temp; } return true ; } template <class T >bool CircularLinkList<T>::insertByRear (const T value){ Node<T>* temp=new Node <T>(value); if (!head){ head=temp; tail=temp; temp->next=temp; } else { temp->next=head; tail->next=temp; tail=temp; } } template <class T >bool CircularLinkList<T>::searchByValue (const T value)const { if (!head) return false ; Node<T>*cur=head; while (cur->next!=head){ if (cur->data==value){ return true ; } cur=cur->next; } return false ; } template <class T >void CircularLinkList<T>::printCircularLinkList (){ if (!head){ cerr<<"Circular LinkList is Empty" ; exit (1 ); } else { Node<T>*cur=head; while (cur->next!=head){ cout<<cur->data<<"\t" ; cur=cur->next; } cout<<endl; } }
# 2.5.3 双向链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include <iostream> using namespace std;template <class T >struct Node { T data; Node<T>* prev,next; Node (T value):data (value),prev (nullptr ),next (nullptr ){} }; template <class T >class DoublyLinkList {private : Node<T>*head; public : DoublyLinkList (); DoublyLinkList (const T arr[],const int len); ~DoublyLinkList (); int length () const ; bool insertByFront (const T value) ; bool insertByRear (const T value) ; bool searchByValue (const T value) const ; bool removeByValue (const T value) ; void printDoublyLinkList () const ; } template <class T >DoublyLinkList<T>::DoublyLinkList (){ head=new Node<T>; head->prev=nullptr ; head->next=nullptr ; } template <class T >DoublyLinkList<T>::DoublyLinkList (const T arr[],const int len){ for (int i=0 ;i<len;i++){ insertByRear (arr[i]); } } template <class T >DoublyLinkList<T>::~DoublyLinkList (){ Node<T>*cur=head; while (cur){ Node<T>* temp=cur; cur=cur->next; delete temp; } } template <class T >int DoublyLinkList<T>::length ()const { if (!head) return 0 ; int len=0 ; Node<T>* cur=head; while (cur->next!=head){ cur=cur->next; len++; } return len; }