链式存储(建议)
- 优点:插入与删除元素方便,时间复杂度为O(1)
- 缺点:查找元素不方便,时间复杂度为O(n)
每个节点包括:存储元素本身的数据域和存储下一个节点地址的指针域
例:a知道b在哪里,b知道c在哪里,那么a要知道c在哪里,就要找到b,才能知道c在哪里。
链表中第一个节点成为头节点,最后一个叫做尾节点。头节点一般情况不存储数据,尾节点的指针域为空。
链表一般有:单向链表、循环链表与双向链表。
单向链表
单向链表的建立
struct node{
int data;
node *next;
}
node *head,*tail;
head = new node;
nead -> next = NULL;
tail = head;
//建立一个节点
node *p;
p = new node;
cin >> p -> data;
p -> next=NULL;
tail -> next = p;
tail = p;
打印单链表
p = head -> next;
while(p != NULL){
cout << p -> data << " ";
p = p -> next;
}
查找链表中值为n的节点
p = head -> next;
while(p -> data != n && p -> next != NULL){
p = p -> next;
}
删除链表中p节点的下一个节点
p -> next = p -> next -> next;
在p节点之后插入一个节点s
s -> next = p -> next;
p -> = s;
————————————————————不太华丽的分割线——————————————————
循环链表
循环链表 = 单向链表成一个环
tail -> next = head;
————————————————————不太华丽的分割线——————————————————
双向链表
每个节点有两个指针域,一个指向上一个节点,另一个指向下一个节点。
他的访问、插入、删除更方便,快捷,但是空间更大了。
链表的建立
struct node{
int data;
node *pre,*next;
}
删除节点
p -> pre -> next = p -> next;
p -> next -> pre = p -> pre;
在p节点之后插入一个节点s
s -> next = p -> next;
p -> next -> pre = s;
s -> pre = p;
p -> next = s;
在p节点之前插入一个节点s
s -> pre = p -> pre;
p -> pre -> next = s;
s -> next = p;
p -> pre = s;