单链表
单链表
概念
与数组不同的是链表的存储单元不一定是连续的
每个结点除了数据域之外保存了后继指针
关于头节点和头指针
头指针指的是链表中第一个结点的存储位置(若无头节点则指针指向第一个节点,否则指向头节点)
头节点则是为了对第一个元素前插入/删除节点时,与其他节点操作一致
链表可以没有头节点但不可以没有头指针
c++实现(建立,插入,删除,反转,打印)
#include<iostream>
using namespace std;
struct Node {
int elem;
Node* next;
Node(int e) :elem(e), next(nullptr) {}
};
class List {
public:
List() {
head = new Node(0);
}
void insert(const int& e) { //头插法,结合find函数可以再指定元素前插入
Node* node = new Node(e);
node->next= head->next;
head->next = node;
++head->elem; //头节点的数据域记录链表长度
}
void remove(const int& e) { //删除指定节点
Node* node = find(e);
Node* temp = node->next;
node->next = node->next->next;
delete temp;
}
Node* find(const int& e) { //返回的是查找结点的上一个元素
Node* node = head;
while (node)
{
if (node->next->elem == e)
break;
node = node->next;
}
return node;
}
void reverse() { //反转链表
Node* first = head->next;
Node* second = head->next->next;
Node* third = head->next->next->next;
first->next = nullptr;
while (third) {
second->next = first;
first = second;
second = third;
third = third->next; //如果只用俩指针p,q,这一步就会出错
}
second->next = first;
head->next = second;
}
void print()
{
for(Node * node = head->next;node;node=node->next){
cout << node->elem <<' ';
}
cout << endl;
}
private:
Node* head; //若需要尾插法,则需要尾指针tail
};
int main()
{
List myList;
for (int i = 0; i < 10; ++i)
myList.insert(i);
myList.print();
myList.remove(4);
myList.print();
myList.reverse();
myList.print();
}
1)尾插法需要声明尾指针Node* tail;
并且在构造函数中初始化为nullptr
将insert函数改成
void insert(const int& e) {
Node* node = new Node(e);
if (!head->next)
head->next = node;
if (tail == nullptr)
tail = node;
else
tail->next = node;
tail = node;
++head->elem;
}
2)插入指定元素之前
void insert_position(const int& e, int p) {
Node* pos = find(p);
Node* node = new Node(e);
node->next = pos->next;
pos->next = node;
}
3)另外链表反转的错误写法是
void reverse() { //反转链表
Node* p = head->next;
Node* q = head->next->next;
p->next = nullptr;
while (q->next) { //不管怎么样,得用仨指针
q->next = p;
p = q;
q = q->next; //导致链表原地打转
}
q->next = p;
head->next = q;
}
保持学习,保持思考,保持对世界的好奇心!