文章目录
1.结构体
struct Node
{
int Data;
Node * next;
};
2.链表头部插入
Node * Insert_head(Node * & head, int value)
{
Node * p = new Node;
p->data = value;
if(head == NULL)
{
head = p;
head->next = NULL;
}
else
{
p->next = head;
head = p;
}
return head;
}
3.链表尾部插入
Node * Insert_End(Node * & head, int value)
{
Node * q = head;
Node * p = new Node;
p->data = value;
if(head == NULL)
{
head = p;
head->next = NULL;
}
else
{
while(q->next != NULL)
{
q = q->next;
}
q->next = p;
}
return head;
}
4.链表打印
void PrintList(Node * head)
{
Node * p = head;
while(p!=NULL)
{
cout << p->data << endl;
p=p->next;
}
}
5.获取链表长度
int GetLength(Node * head)
{
Node * p = head;
int len = 0;
while(p != NULL)
{
p = p->next;
len++;
}
return len;
}
6.链表插入
Node * Insert(Node *& head, int value)
{
Node * p0, *p1, *p2;
p0 = new Node;
p0->data = value;
p1 = head;
if(head == NULL)
{
head = p0;
head->next = NULL;
return head;
}
//找到插入的位置
while(p0->data > p1->data && p1->next != NULL)
{
p2 = p1;
p1 = p1->next;
}
if(p0->data <= p1->data)
{
if(p1 == head)
{
//头部插入
p0->next = head;
head = p0;
}
else
{
//中间插入
p2->next = p0;
p0->next = p1;
}
}
else
{
//尾部插入
p1->next = p0;
p0->next = NULL;
}
return head;
}
7.链表删除
Node * Delete(Node * head, int value)
{
Node * p, *q;
p = head;
while(p->data != value && p->next != NULL)
{
q = p;
p = p->next;
}
if(p->data == value)
{
if(p == head)
{
head = p->next;
delete p;
}
else
{
q->next = p->next;
delete p;
}
}
else
{
cout << "not find data" << endl;
}
return head;
}
8.链表清空
void Destruct(Node * head)
{
Node *p, *q;
p = head;
q = NULL;
while(p!=NULL)
{
q = p;
p = p->next;
delete q;
}
}
9.链表逆序(循环方法)
Node * ReverseList(Node * head)
{
Node *p, *q, *r;
p = head; //一开始p指向第一个节点
q = p->next; //q指向第二个节点
while(q != NULL) //如果没到链尾
{ //以第一次循环为例
r = q->next; //r暂时存储第三个节点
q->next = p; //没有执行这句前,q->next指向第三个节点
p = q; //执行之后p指向第二个节点
q = r; //之后p指向第二个节点
}
head->next = NULL; //最后原来的链头变为链尾
head = p; //原来的链尾变成链头
return head;
}
10.链表逆序(递归方法)
将链表分为当前表头节点和其余节点,递归的思想就是,先将当前的表头节点从链表中拆出来,然后对剩余的节点进行逆序,最后将当前的表头节点连接到新链表的尾部,这里边的关键点是头节点head的下一个节点head->next将是逆序后的新链表的尾节点,也就是说,被摘除的头接点head需要被连接到head->next才能完成整个链表的逆序
Node * ReverseList1(Node * head)
{
if(head == NULL || head->next == NULL)
{
return head;
}
Node* list = ReverseList1(head->next);
// 将当前节点的下一个节点的指针指向当前节点,实现逆转
head->next->next = head;
head->next = NULL;
return list ;
}
11.两个链表有序合并后依然有序(循环方法)
Node * Merge(Node * head1, Node * head2)
{
Node * head = NULL;
if(head1 == NULL)
{
return head2;
}
if(head2 == NULL)
{
return head1;
}
if(head1->data <= head2->data)
{
head = head1;
head1 = head1->next;
}
else
{
head = head2;
head2 = head2->next;
}
Node * temp = head;
while(head1 != NULL && head2 != NULL)
{
if(head1->data <= head2->data)
{
temp->next = head1;
head1 = head1->next;
temp = temp->next;
}
else
{
temp->next = head2;
head2 = head2->next;
temp = temp->next;
}
}
if(head1 == NULL)
{
temp->next = head2;
}
if(head2 = NULL)
{
temp->next = head1;
}
return head;
}
12.两个链表有序合并后依然有序(递归方法)
Node * MergeRecursive(Node * head1, Node * head2)
{
Node * head = NULL;
if(head1 == NULL)
{
return head2;
}
if(head2 == NULL)
{
return head1;
}
if(head1->data < head2->data)
{
head = head1;
head->next = MergeRecursive(head1->next, head2);
}
else
{
head = head2;
head->next = MergeRecursive(head1, head2->next);
}
return head;
}
13.判断一个链表是否有环
bool ExitLoop(Node * head)
{
Node * Fast = head;
Node * Slow = head;
while(Fast != NULL && Fast->next != NULL)
{
Fast = Fast->next->next;
Slow = Slow->next;
if(Fast == Slow)
{
return true;
}
}
return false;
}
14.找到环的入口点
从链表起点head开始到入口点的距离,与从slow和fast的相遇点到入口点的距离相等
Node * FindLoopStart(Node * head)
{
Node * Fast = head;
Node * Slow = head;
while(Fast != NULL && Fast->next != NULL)
{
Fast = Fast->next->next;
Slow = Slow->next;
if(Fast == Slow)
{
break;
}
}
if(Fast == NULL || Fast->next == NULL)
{
return NULL;
}
Node * p1 = head;
Node * p2 = Slow;
while(p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
15.环上节点个数
slow和fast的相遇后,Slow再走一圈就是环的长度
int GetLoopLength(Node * head)
{
Node * Fast = head;
Node * Slow = head;
while(Fast != NULL && Fast->next != NULL)
{
Fast = Fast->next->next;
Slow = Slow->next;
if(Fast == Slow)
{
break;
}
}
if(Fast == NULL || Fast->next == NULL)
{
return 0;
}
Node * p = Slow->next;
int len = 1;
while(p != Slow)
{
p = p->next;
len++;
}
return len;
}
16.判断两个链表是否相交并找出交点
Node * Find_Node(Node * head1, Node * head2)
{
if(head1 == NULL || head2 == NULL)
{
return NULL;
}
Node * p1 = head1;
Node * p2 = head2;
int len1 = 0;
int len2 = 0;
while(p1->next != NULL)
{
len1++;
p1 = p1->next;
}
while(p2->next != NULL)
{
len2++;
p2 = p2->next;
}
//不相交
if(p1 != p2)
{
return NULL;
}
int diff = abs(len1 - len2);
if(len1 > len2)
{
p1 = head1;
p2 = head2;
}
else
{
p1 = head2;
p2 = head1;
}
for(int i=0; i<diff; i++)
{
p1 = p1->next;
}
while(p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
在双指针遍历的过程中,如果一个指针达到链表末尾后,将其重定向到另一个链表的头部,
这就保证了两个指针在相遇点相遇。这个方法不受链表长度差异的影响。
Node * getIntersectionNode(Node* head1, Node* head2)
{
if (head1 == NULL || head2 == NULL) {
return NULL;
}
Node* p1 = head1;
Node* p2 = head2;
while (p1 != p2)
{
p1 = p1==NULL? p2:p1->next;
p2 = p2==NULL? p1:p2->next;
}
return p1;
}