版权声明:转载请附上文章地址https://blog.csdn.net/qq_42672839
什么是链表结构:
链表结构是由许多节点构成的,每个节点都包含两部分:
- 数据部分:保存该节点的实际数据。
- 地址部分:保存的是下一个节点的地址。
链表的特点:
结点在存储器中的位置是任意的,即逻辑上相邻的数 据元素在物理上不一定相邻
访问时只能通过头指针进入链表,并通过每个结点的 指针域向后扫描其余结点,所以寻找第一个结点和最后一 个结点所花费的时间不等
链表的优点:
数据元素的个数可以自由扩充 、插入、删除等操作不必移动数据,只需 修改链接指针,修改效率较
链表的缺点:
存储密度小 、存取效率不高,必须采用顺序存取,即存 取数据元素时,只能按链表的顺序进行访问
链表的类型有多种:单链表,双链表,有序链表
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
链表与数组比较:
优点:链表不需要确定长度大小,也不需要连续的内存空间,
缺点:由于不是连续的空间,所以查找元素比较吃力;相比数组只存储元素,链表的元素还要存储其它元素的地址,内存开销相对增大。
单链表:
java代码实现如下:
public class LinkedListDemo1 { //表示整个链表对象
private Node first; //链表对象的第一个引用
public LinkedListDemo1(){
}
public Node getFirst() {
return first;
}
public void setFirst(Node first) {
this.first = first;
}
class Node{ //节点对象
Item item; //存储的数据对象
Node next; //下一个节点对象的引用
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
}
c语言
单向链表的节点包括:
- 数据域:用于存储数据元素的值。
-
指针域(链域):用于存储下一个结点地址或者说指向其直接后继结点的指针。
struct Node{
int value;
Node * next;
};
1.2双向链表
双向链表的节点包括:
- 数据域:用于存储数据元素的值。
- 左指针域(左链域):用于存储上一个结点地址或者说指向其直接前继结点的指针。
-
右指针域(右链域):用于存储下一个结点地址或者说指向其直接后继结点的指针。
struct DNode{
int value;
DNode * left;
DNode * right;
};
1.3翻转链表
题意即为将链表反过来,即,原本为p1-p2-p3翻转为p3-p2-p1。读者需自行画图体会指针操作。
//翻转链表
Node * reverseLinkedList(Node* head,int k){
Node *reversedHead = NULL;
Node *pNode = head;
Node *pre = NULL;
while (pNode!=NULL) {
if (pNode->next==NULL) {
reversedHead = pNode;
}
Node* nxt = pNode->next;
pNode->next = pre;
pre=pNode;
pNode=nxt;
}
return reversedHead;
}
1.4判断链表是否有环路,获取连接点,计算环的长度
判断是否含有环:slow和fast,slow指针每次走一步,fast指针每次走两步,若是链表有环,fast必能追上slow(相撞),若fast走到NULL,则不含有环。
//判断是否含有环
bool containLoop(Node* head){
if (head==NULL) {
return false;
}
Node* slow = head;
Node* fast = head;
while (slow!=fast&&fast->next!=NULL) {
slow = slow->next;
fast = fast->next->next;
}
if (fast==NULL) {
return false;
}
return true;
}
判断环的长度:在相撞点处,slow和fast继续走,当再次相撞时,slow走了length步,fast走了2*length步,length即为环得长度。
//获得环的长度
int getLoopLength(Node* head){
if (head==NULL) {
return 0;
}
Node* slow = head;
Node* fast = head;
while (slow!=fast&&fast->next!=NULL) {
slow = slow->next;
fast = fast->next->next;
}
if (fast==NULL) {
return 0;
}
//slow和fast首次相遇后,slow和fast继续走
//再次相遇时,即slow走了一圈,fast走了两圈
int length = 0;
while (slow!=fast) {
length++;
slow = slow->next;
fast = fast->next->next;
}
return length;
}