目录
相信大家对单链表都不是很陌生,在这里介绍一下单链表的基本的操作和相关问题。
1.单链表的定义
typedef struct Node
{
int data;
Node* next;
}Node;
typedef struct Node* LinkList;//定义链表
2.获取单链表的第i个元素
bool GetElem(LinkList l, int i, int* e)
{
int j;
LinkList p;
p = l->next;
j = 1;
while (p && j < i)
{
p = p->next;
++j;
}
if (!p)
{
return false;
}
*e = p->data;
return true;
}
3.单链表的插入操作
bool LinkInsert(LinkList l, int i, int e)
{
int j;
LinkList p, s;
p = l;
while (p && j < i)
{
p = p->next;
++j;
}
if (!p)
{
return false;
}
s = (Node*)malloc(sizeof(Node));//申请新的结点
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
4.单链表的删除操作
bool ListDelete(LinkList l, int i, int* e)
{
int j;
LinkList p, q;
p = l;
j = 1;
while (p->next && j < i)
{
p = p->next;
++j;
}
if (!(p->next))
{
return false;
}
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return true;
}
5.单链表的整表删除
bool ClearList(LinkList l)
{
LinkList p, q;
p = l->next;
while (p)
{
q = p->next;
free(p);
p = q;
}
l->next = NULL;
return true;
}
6.判断两个单链表是否相交
bool IsCUt(LinkList pList1, LinkList pList2)
{
int len1 = GetLength(pList1);
int len2 = GetLength(pList2);
Node* pLong = pList1;
Node* pShort = pList2;
int len = len1 - len2;
if (len < 0)
{
pLong = pList2;
pShort = pList1;
len = len2 - len1;
}
//先将长的链表遍历到和短链表长度一样的地方
for (int i = 0; i < len; ++i)
{
pLong = pLong->next;
}
while (pLong != NULL && pShort != NULL && pLong != pShort)
{
pLong = pLong->next;
pShort = pShort->next;
}
//由于pLong和pShort后面的长度是一样的,且是同时向后遍历的,如果跳出循环的条件不是
//pLong==null,那么也不是pShort==null,一定是pLong==pShort且不等于null.
if (pLong != NULL)
{
return true;
}
return false;
}
7.如果两个链表相交,如何寻找相交的节点
在第6个问题中,当条件:
if (pLong != NULL)
成立的时候,pLong和pShort会同时指向两个链表的相交点。
8.判断一个单链表是否有环
解法1:可以用hashSet,将链表依次遍历存入hashSet,如果在遍历的过程中出现了相同的节点,就表明这个链表是有环的。
解法2:设置两个指针,fast和slow,fast每次向前遍历两个节点,slow每次向前遍历一个节点,如果链表有环,那么slow会很快追上fast节点。
bool hasCircle(LinkList l)
{
Node* fast = l;
Node* slow = l;
while (fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return true;
}
}
return false;
}
9.如果一个链表有环,如何找到环的入口
10.找到单链表中的倒数第k个节点
11.两个有序链表的合并
12.找链表的中间节点
可以设立两个指针,,fast和slow,fast每次向前遍历两个节点,slow每次向前遍历一个节点,当fast遍历到链表末端的时候,slow正好指向链表的中间节点。
Node* getMid(LinkList l)
{
Node* fast = l;
Node* slow = l;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}