1.从尾到头打印单链表
void RPrintList(pList plist);
从尾到头打印单链表,而不能改变链表本身,可以用递归很好的实现
void RPrintList(pList plist)
{
if (plist == NULL)
{
return;
}
else if (plist->next == NULL)
{
printf("%d-->", plist->data);
}
else
{
RPrintList(plist->next);
printf("%d-->", plist->data);
}
}
具体测试:
void test1()
{
pList plist = NULL;
InitLinkList(&plist);
PushFront(&plist, 1);
PushFront(&plist, 2);
PushFront(&plist, 3);
PushFront(&plist, 4);
PushFront(&plist, 5);
PrintList(plist);
RPrintList(plist);
}
int main()
{
test1();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
2. 删除一个无头单链表的非尾节点(不能遍历链表)
void EraseNotTail(pNode pos);
首先我们可以先把要删除节点的下一个节点保存下来,然后将该节点和它下一个节点的值进行交换,最后删除掉那个保存的下个节点
void EraseNotTail(pNode pos)
{
pNode del = NULL;
assert(pos->next);
del = pos->next;
pos->data = del->data;
pos->next = del->next;
free(del);
del = NULL;
}
具体测试:
void test2()
{
pList plist = NULL;
pNode pos = NULL;
InitLinkList(&plist);
PushFront(&plist, 1);
PushFront(&plist, 2);
PushFront(&plist, 3);
PushFront(&plist, 4);
PushFront(&plist, 5);
PrintList(plist);
pos = Find(plist, 2);
EraseNotTail(pos);
PrintList(plist);
}
int main()
{
test2();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
3. 在无头单链表的一个非头节点前插入一个节点
void InsertFrontNode(pNode pos, DataType d);
同上一题类似,我们可以在指定位置的后面插入一个新节点,然后交换新节点和指定节点的数据即可
void InsertFrontNode(pNode pos, DataType d)
{
pNode newNode = BuyNode(d);
DataType tmp = 0;
newNode->next = pos->next;
pos->next = newNode;
//交换数据
tmp = pos->data;
pos->data = newNode->data;
newNode->data = tmp;
}
具体测试:
void test3()
{
pList plist = NULL;
pNode pos = NULL;
InitLinkList(&plist);
PushFront(&plist, 1);
PushFront(&plist, 2);
PushFront(&plist, 3);
PushFront(&plist, 4);
PushFront(&plist, 5);
PrintList(plist);
pos = Find(plist, 2);
InsertFrontNode(pos, 6);
PrintList(plist);
}
int main()
{
test3();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
4. 单链表实现约瑟夫环
void JosephCycle(pList plist, int k);
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
void JosephCycle(pList plist, int k)
{
pNode cur = plist;
pNode del = NULL;
int num = 0;
while (1)
{
num = k;
if (cur == cur->next)
{
break;
}
while (--num)
{
cur = cur->next;
}
printf("%d ", cur->data);
del = cur->next;
cur->data = del->data;
cur->next = del->next;
free(del);
}
printf("\n剩下人的编号:%d\n", cur->data);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
具体测试:(在这里我们就用约瑟夫的小故事,给上41个人,每次报数报到3的人出列)
void test4()
{
pList plist = NULL;
int i = 0;
InitLinkList(&plist);
for (i = 41; i >= 1; i--)
{
PushFront(&plist, i);
}
Find(plist, 41)->next = plist;
JosephCycle(plist, 3);
}
int main()
{
test4();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
5. 逆置/反转单链表
void ReverseList(pList *pplist);
与第一题从尾到头打印单链表不同的是,逆序链表我们要改变的是链表本身。可以先将链表的第一个节点取下来,保存在一个newHead中,随后依次把剩下的节点取下来连在第一个节点的前面。最后将newHead赋给管理之前链表得到指针pplist
void ReverseList(pList *pplist)
{
pNode cur = *pplist;
pNode tmp = NULL;
pNode newHead = NULL;
assert(pplist);
if ((*pplist == NULL) || (cur->next == NULL))
{
return;
}
while (cur)
{
tmp = cur;
cur = cur->next;
tmp->next = newHead;
newHead = tmp;
}
*pplist = newHead;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
逆序链表的测试我们在下一个题中一起展示
6. 单链表排序
void BubbleSort(pList *pplist);
因为现在暂时还没有接触快速排序,所以在这里只实现冒泡法排序链表
void BubbleSort(pList *pplist)
{
pNode cur = *pplist;
pNode tail = NULL;
assert(pplist);
if ((cur == NULL) || (cur->next == NULL))
{
return;
}
while (cur->next != tail)
{
while (cur->next != tail)
{
if ((cur->data) > (cur->next->data))
{
DataType tmp = cur->data;
cur->data = cur->next->data;
cur->next->data = tmp;
}
cur = cur->next;
}
tail = cur;
cur = *pplist;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
具体测试
void test6()
{
pList plist = NULL;
pNode pos = NULL;
InitLinkList(&plist);
PushFront(&plist, 7);
PushFront(&plist, 2);
PushFront(&plist, 4);
PushFront(&plist, 3);
PushFront(&plist, 5);
PushFront(&plist, 1);
PushFront(&plist, 6);
printf("正常:");
PrintList(plist);
ReverseList(&plist);
printf("逆序后:");
PrintList(plist);
BubbleSort(&plist);
printf("排序后:");
PrintList(plist);
}
int main()
{
test6();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
7.合并两个有序链表,合并后依然有序
pList Merge(pList *pplist1, pList *pplist2);//合并两个有序单链表,合并后依然有序
pList DMerge(pList *pplist1, pList *pplist2);//递归实现两条链表合并
在这里我们分别用递归和非递归进行实现,直接上代码:
pList Merge(pList *pplist1, pList *pplist2)
{
pNode cur1 = *pplist1;
pNode cur2 = *pplist2;
pList newHead = NULL;
pNode tail = NULL;
assert(pplist1);
assert(pplist2);
if ((*pplist1 == NULL) && (*pplist2 == NULL))
{
return NULL;
}
if (*pplist1 == *pplist2)
{
return *pplist1;
}
if (*pplist1 == NULL)
{
return *pplist2;
}
if (*pplist2 == NULL)
{
return *pplist1;
}
if ((cur1->data) > (cur2->data))
{
newHead = cur2;
cur2 = cur2->next;
}
else
{
newHead = cur1;
cur1 = cur1->next;
}
newHead->next = NULL;
tail = newHead;
while (cur1&&cur2)
{
if ((cur1->data) > (cur2->data))
{
tail->next = cur2;
cur2 = cur2->next;
}
else
{
tail->next = cur1;
cur1 = cur1->next;
}
tail = tail->next;
tail->next = NULL;
}
if (cur1 == NULL)
{
tail->next = cur2;
}
else if (cur2 == NULL)
{
tail->next = cur1;
}
return newHead;
}
pList DMerge(pList *pplist1, pList *pplist2)
{
pNode cur1 = *pplist1;
pNode cur2 = *pplist2;
pList newHead = NULL;
pNode tail = NULL;
assert(pplist1);
assert(pplist2);
if ((cur1 == NULL) && (cur2 == NULL))
{
return NULL;
}
if (cur1 == cur2)
{
return cur1;
}
if (cur1 == NULL)
{
return cur2;
}
if (cur2 == NULL)
{
return cur1;
}
if ((cur1->data) > (cur2->data))
{
newHead = cur2;
cur2 = cur2->next;
}
else
{
newHead = cur1;
cur1 = cur1->next;
}
newHead->next = NULL;
if (cur1 == NULL || cur2 == NULL);
{
tail = newHead;
tail->next = DMerge(&cur1, &cur2);
}
return newHead;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
具体测试:
void test7()
{
pList plist1 = NULL;
InitLinkList(&plist1);
PushFront(&plist1, 9);
PushFront(&plist1, 7);
PushFront(&plist1, 5);
PushFront(&plist1, 3);
PushFront(&plist1, 1);
pList plist2 = NULL;
InitLinkList(&plist2);
PushFront(&plist2, 10);
PushFront(&plist2, 8);
PushFront(&plist2, 6);
PushFront(&plist2, 4);
PushFront(&plist2, 2);
PushFront(&plist2, 0);
pList newList1 = NULL;
newList1 = Merge(&plist1, &plist2);
PrintList(newList1);
pList newList2 = NULL;
newList2 = DMerge(&plist1, &plist2);
PrintList(newList2);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
8. 查找单链表的中间节点,要求只能遍历一次链表
pNode FindMidNode(pList plist);
查找链表中间节点,我们可以定义两个指针,快指针每次次走两步,慢指针每次走一步,当快指针到达链表尾部时,慢指针所在的位置就是中间节点的位置。
pNode FindMidNode(pList plist)
{
pNode fast = plist;
pNode slow = plist;
if (plist == NULL)
{
return NULL;
}
while (fast&&fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
具体测试:
void test8()
{
pNode pos = NULL;
pList plist1 = NULL;
InitLinkList(&plist1);
PushFront(&plist1, 9);
PushFront(&plist1, 7);
PushFront(&plist1, 5);
PushFront(&plist1, 3);
PushFront(&plist1, 1);
pList plist2 = NULL;
InitLinkList(&plist2);
PushFront(&plist2, 10);
PushFront(&plist2, 8);
PushFront(&plist2, 6);
PushFront(&plist2, 4);
PushFront(&plist2, 2);
PushFront(&plist2, 0);
pList newList1 = NULL;
newList1 = Merge(&plist1, &plist2);
PrintList(newList1);
pos = FindMidNode(newList1);
printf("中间节点:%d\n", pos->data);
}
int main()
{
test8();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
9. 删除链表的倒数第K个结点
void DelKNode(pList plist, int k);
同样的,定义两个指针。一个指针first先走上K 步,然后第二个指针second再和first指针同时走,当first指针到达链表尾部时,second指针所在的位置就为倒数第K个节点的位置,随后我们用之前讲过交换数据的方法删除即可
(注意,因为是用交换删除的方法,如果K=1,则它没有下一个节点。我们可以对这种情况进行单独处理,这时候函数就和尾删一样了,我在这里直接调用尾删的接口)
void DelKNode(pList plist, int k)
{
pNode first = plist;
pNode second = plist;
if (k == 1)
{
PopBack(&plist);
return;
}
while (first&&first->next)
{
first = first->next;
if (--k <= 0)
{
second = second->next;
}
}
if (k <= 0)
{
pNode del = second->next;
second->data = del->data;
second->next = del->next;
free(del);
del = NULL;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
具体测试:
void test9()
{
pList plist = NULL;
InitLinkList(&plist);
PushFront(&plist, 1);
PushFront(&plist, 2);
PushFront(&plist, 3);
PushFront(&plist, 4);
PushFront(&plist, 5);
PushFront(&plist, 6);
PushFront(&plist, 7);
PrintList(plist);
DelKNode(plist, 1);
PrintList(plist);
DelKNode(plist, 3);
PrintList(plist);
}
int main()
{
test9();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
10. 判断单链表是否带环?若带环,求环的长度?求环的入口点?
pNode CheckCycle(pList plist);
int GetCircleLength(pNode meet);
pNode GetCircleEntryNode(pNode meet, pList plist);
(1)判断链表是否带环
还是定义上两个指针,快指针每次走两步,慢指针每次走一步,如果链表带环的话,两个指针必定会相遇,而且相遇点一定在环上。
pNode CheckCycle(pList plist)
{
pNode fast = plist;
pNode slow = plist;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return slow;
}
}
return NULL;
}
(2)求环的长度
定义一个指针,从相遇点(见链表判环问题)开始走,在定义一个计数器,每走一步计数器家家,当下次到达相遇点时计数器的大小就是环的长度了。
int GetCircleLength(pNode meet)
{
int count = 0;
pNode cur = meet;
do
{
cur = cur->next;
count++;
} while (cur != meet);
return count;
}
(3)求环的入口点
在这里我们介绍两种方法
方法一:从开始到环入口点的距离x = 环长度len的整数倍c*len - 从环入口点到相遇点的距离y
定义一个指针从开始出发,另一个指针从相遇点出发,两个指针再次相遇的点就为入口点
详见下图:
方法二:定义两个指针,一个先走环的长度步,另外一个在开始走,两个指针相遇的地方就为环的入口点
pNode GetCircleEntryNode(pNode meet, pList plist)
{
pNode first = plist;
pNode second = plist;
int num = GetCircleLength(meet);
while (num--)
{
first = first->next;
}
while (first != second)
{
first = first->next;
second = second->next;
}
return first;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
具体测试:
void test10()
{
pList plist = NULL;
pNode pos = NULL;
pNode entry = NULL;
InitLinkList(&plist);
PushFront(&plist, 1);
PushFront(&plist, 2);
PushFront(&plist, 3);
PushFront(&plist, 4);
PushFront(&plist, 5);
PushFront(&plist, 6);
PushFront(&plist, 7);
PrintList(plist);
DelKNode(plist, 1);
PrintList(plist);
DelKNode(plist, 3);
PrintList(plist);
Find(plist, 1)->next = Find(plist, 4);
pos = CheckCycle(plist);
if (pos == NULL)
{
printf("不带环\n");
}
else
{
printf("带环\n");
printf("相遇点:%d\n", pos->data);
}
printf("环长度:%d\n", GetCircleLength(pos));
entry = GetCircleEntryNode(pos, plist);
printf("入口点:%d\n", entry->data);
}
int main()
{
test10();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
11. 判断两个链表是否相交,若相交,求交点。(假设链表不带环)
pNode CheckCross(pList p1, pList p2);
在这里我们只讨论两条链表都不带环的情况
对于求交点的问题我们也给出两种实现方法:
方法一:将两条相交的链表连成一个带环的链表,将第一个链表尾部的next指向第二个链表的头部再利用之前实现过的接口,把问题转化成求环的入口点
方法二:第一条链表的长度为len1,第二条链表的长度为len2,定义一个指针从长度长的链表先走|len1-len2|步,第二个指针再从长度短的链表走,当两个指针第一次指向地址相同的那个节点,则该节点为相交节点。
pNode CheckCross(pList p1, pList p2)
{
pNode cur1 = p1;
pNode cur2 = p2;
int len1 = 0;
int len2 = 0;
int num = 0;
if ((cur1 == NULL) || (cur2 == NULL))
{
return NULL;
}
while (cur1->next)
{
cur1 = cur1->next;
len1++;
}
while (cur2->next)
{
cur2 = cur2->next;
len2++;
}
if (cur1 == cur2)
{
num = abs(len1 - len2);
if (len1 > len2)
{
cur1 = p1;
cur2 = p2;
}
else
{
cur2 = p1;
cur1 = p2;
}
for (int i = 0; i < num; i++)
{
cur1 = cur1->next;
}
while (cur1 != cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}
else
{
return NULL;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
具体测试:
void test11()
{
pList plist1 = NULL;
pNode cross = NULL;
InitLinkList(&plist1);
PushFront(&plist1, 10);
PushFront(&plist1, 9);
PushFront(&plist1, 7);
PushFront(&plist1, 5);
PushFront(&plist1, 3);
PushFront(&plist1, 1);
pList plist2 = NULL;
InitLinkList(&plist2);
PushFront(&plist2, 6);
PushFront(&plist2, 4);
PushFront(&plist2, 2);
PushFront(&plist2, 0);
Find(plist2, 6)->next = Find(plist1, 5);
cross = CheckCross(plist1, plist2);
printf("相交点:%d\n", cross->data);
}
int main()
{
test11();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
12. 复杂链表的复制。
pComplexNode BuyComplexNode(DataType d);
void PrintComplexList(pComplexNode p);
pComplexNode CopyComplexList(pComplexNode head);
复杂链表:一个链表的每个节点,有一个指向next指针指向下一个节点,还有一 个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表, 返回复制后的新链表
先来看看复杂链表的结构:
typedef struct ComplexNode
{
DataType *data;
struct ComplexNode *next;
struct ComplexNode *random;
}ComplexNode, *pComplexNode;
我们可以把复杂链表的复制分为三个部分
(1)、复制复杂链表的每个节点,并插入到该节点的后面
(2)、调整复制节点的random指针指向
(3)、分离两条链表
贴一张我在实现过程中画的草图,希望能够帮助大家更好的理解(草图!草图!草图!)
紫色区域为random指针域,绿色区域为next指针域
我们可以看到,复制节点的random指向刚好就是指向它那个节点random指针的next的指向。
pComplexNode BuyComplexNode(DataType d)
{
pComplexNode newNode = (pComplexNode)malloc(sizeof(ComplexNode));
if (newNode == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
newNode->data = d;
newNode->next = NULL;
newNode->random = NULL;
return newNode;
}
void PrintComplexList(pComplexNode p)
{
pComplexNode cur = p;
while (cur)
{
printf("[%d]-->(%d)-->", cur->data, cur->random->data);
cur = cur->next;
}
printf("NULL\n");
}
pComplexNode CopyComplexList(pComplexNode head)
{
pComplexNode pold = head;
pComplexNode cur = NULL;
pComplexNode newNode = NULL;
pComplexNode newHead = NULL;
while (pold)
{
cur = pold->next;
newNode = BuyComplexNode(pold->data);
pold->next = newNode;
newNode->next = cur;
pold = cur;
}
pold = head;
while (pold)
{
newNode = pold->next;
if (pold->random)
{
cur = pold->random->next;
newNode->random = cur;
}
pold = newNode->next;
}
pold = head;
if (pold != NULL)
{
newHead = pold->next;
}
while (pold->next->next)
{
newNode = pold->next;
pold->next = newNode->next;
pold = newNode->next;
newNode->next = pold->next;
}
pold->next = NULL;
return newHead;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
具体测试:
void test12()
{
pComplexNode newList = NULL;
pComplexNode p1 = NULL;
pComplexNode p2 = NULL;
pComplexNode p3 = NULL;
pComplexNode p4 = NULL;
p1 = BuyComplexNode(1);
p2 = BuyComplexNode(2);
p3 = BuyComplexNode(3);
p4 = BuyComplexNode(4);
p1->next = p2;
p2->next = p3;
p3->next = p4;
p1->random = p3;
p2->random = p4;
p3->random = p2;
p4->random = p3;
PrintComplexList(p1);
newList = CopyComplexList(p1);
PrintComplexList(newList);
}
int main()
{
test12();
system("pause");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29