阿牧路泽

哪有那么多坚强,无非是死扛罢了
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

2、【线性结构】数组、单向链表及双向链表

Posted on 2018-03-26 20:10  阿牧路泽  阅读(179)  评论(0编辑  收藏  举报

概要

  线性表是一种线性结构,它是具有相同类型的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 }