数据结构_完成单链表的后续操作实现以及链表面试题

1.初始化链表

2.尾插一个元素到链表中

3.尾删一个元素

4.头插一个元素

5.头删一个元素

6.查找元素在链表中的位置

7.在pos之前插入元素

8.在pos之后插入元素 

9.删除指定位置的元素

10.删除指定值的元素

11.指定值的所有相同元素都删掉.

12.判定链表是否为空

13.求链表的元素个数

14.逆序打印单链表

15.不允许遍历链表, 在 pos之前插入

16.实现约瑟夫环

17.单链表逆置

18.单链表逆置(删掉元素,使其头插)

19.单链表的冒泡排序

20.将两个有序链表, 合并成一个有序链表 

21.查找链表中间节点,只遍历一次

22.找到倒数第k个节点,只遍历一次

23.删除倒数第K个节点

24.判定单链表是否带环. 如果带环返回它们的相遇点

25.如果链表带环, 求出环的长度

26.如果链表带环, 求出环的入口

27.判定两个链表是否相交, 并求出交点 (两个不带环的链表)

28.两个带环链表交点在环上

29.判断两个链表是否相交,并求出交点(两个链表可能带环)

30.返回两个有序链表交集的新链表

31.拷贝复杂链表

32.拷贝复杂链表2


linklist.h

//单向的不带环的不带头节点的链表
#pragma once//防止头文件重复包含
#include<stdio.h>
#include<stdlib.h>
#include<stddef.h>
typedef char LinkNodeType;
typedef struct LinkNode{  //方便使用结构体名
LinkNodeType data;
struct LinkNode* next;//链表的节点里有数据和要指向下一个节点的指针
}LinkNode;
typedef struct ComplexNode{
LinkNodeType data;
struct ComplexNode* next;
struct ComplexNode* random;
}ComplexNode;
void LinkListInit(LinkNode**);//初始化链表
void LinkListDestroy(LinkNode**);
void LinkListPushBack(LinkNode** head, LinkNodeType value);//尾插(可能会修改头指针的指向,所以用**)
void LinkListPopBack(LinkNode** head);//尾删
void LinkListPushFront(LinkNode** head, LinkNodeType value);//头插
void LinkListPopFront(LinkNode** head);//头删
LinkNode* LinkListFind(LinkNode* head, LinkNodeType to_find);//查找元素在链表的位置
void LinkListInsert(LinkNode* pos, LinkNodeType value);//任意位置插入(pos之后)
void LinkListInsertBefore(LinkNode** head, LinkNode* pos, LinkNodeType value);//任意位置插入(pos之前)
void LinkListErase(LinkNode** head, LinkNode* pos);//删除指定位置的元素
void LinkListErase2(LinkNode** head, LinkNode* pos);//删除指定位置的元素(移形换位)
void LinkListRemove(LinkNode** head, LinkNodeType to_delete);//删除指定值的元素
void LinkListRemoveAll(LinkNode** head, LinkNodeType to_delete);  //删除所有指定的元素
int LinkListEmpty(LinkNode* head);//判断链表是否为空
size_t LinkListSize(LinkNode* head);//求链表元素的个数
void LinkListReversePrint(LinkNode* head);//逆序打印单链表
void LinkListInsertBefore2(LinkNode** head, LinkNode* pos, LinkNodeType value);//不允许便利链表,在pos之前插入
LinkNode* JosephCycle(LinkNode* head, size_t food);//约瑟夫环
void LinkListReverse(LinkNode** head);//单链表逆置(改变指针的指向)
void LinkListReverse2(LinkNode** head);//单链表逆置(删掉元素,使其头插)
void LinkListBubbleSort(LinkNode* head);//单链表的冒泡排序
LinkNode* LinkListMerge(LinkNode* head1, LinkNode* head2);// 将两个有序链表, 合并成一个有序链表 
LinkNode* FindMidNode(LinkNode* head);//查找链表中间节点,只遍历一次
LinkNode* FindLastKNode(LinkNode* head, size_t K);//找到倒数第k个节点,只遍历一次
void EraseLastKNode(LinkNode** head, size_t K);  //删除倒数第K个节点
LinkNode* HasCycle(LinkNode* head);//判定单链表是否带环. 如果带环返回它们的相遇点
size_t GetCycleLen(LinkNode* head); //如果链表带环, 求出环的长度
LinkNode* GetCycleEntry(LinkNode* head); //如果链表带环, 求出环的入口
LinkNode* HasCross(LinkNode* head1, LinkNode* head2);//判定两个链表是否相交, 并求出交点 (两个不带环的链表)
LinkNode* CrossIn(LinkNode* head1, LinkNode* head2);//两个带环链表交点在环上
int HasCrossWithCycle(LinkNode* head1, LinkNode* head2); //判断两个链表是否相交,并求出交点(两个链表可能带环)
LinkNode* UnionSet(LinkNode* head1, LinkNode* head2);//返回两个有序链表交集的新链表
ComplexNode* CopyComplex(ComplexNode* head);//拷贝复杂链表

ComplexNode* CopyComplex2(ComplexNode* head);//拷贝复杂链表2


linklist.c

#include "linklist.h"
LinkNode* CreateNode(LinkNodeType value){  //创建新节点
LinkNode* newnode = (LinkNode *)malloc(sizeof(LinkNode));
newnode->data = value;
newnode->next = NULL;
return newnode;
}
void DestroyNode(LinkNode* node){
free(node);
node = NULL;
}


void LinkNodeInit(LinkNode** node){    //初始化链表
*node = NULL;
}
void LinkListPrintChar(LinkNode* head,const char* msg){   //打印函数
printf("[%s]\n", msg);
LinkNode *cur = head;
for (; cur != NULL; cur = cur->next){
printf("[%c|%p] ", cur->data, cur);
}
printf("\n");
}  
void LinkListPushBack(LinkNode **head, LinkNodeType value){//尾插(时间复杂度O(N))
if (head == NULL){ 
//非法输入
return;
}
if (*head == NULL){
//空链表
*head = CreateNode(value);
return;
}     
LinkNode *cur = *head;//cur解引用后非空
while (cur->next != NULL){
cur = cur->next;//(取下一个元素的地址)
}
LinkNode* newnode = CreateNode(value);
cur->next = newnode;
return;
}
void LinkListPopBack(LinkNode** head){//尾删(时间复杂度为O(N))
if (head == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
if ((*head)->next == NULL){
//只有一个元素时会修改头指针的指向
DestroyNode(*head);
*head = NULL;
return;
}
LinkNode* cur = *head;//要删除最后一个,使前一个指向空 
LinkNode* pre = NULL;
while (cur->next != NULL){
pre = cur;
cur = cur->next;
}
pre->next = NULL;
DestroyNode(cur);
return;
}
void LinkListPushFront(LinkNode** head, LinkNodeType value){//头插(时间复杂度O(1))
if (head == NULL){
//非法输入
return;
}
LinkNode* newnode = CreateNode(value);
newnode->next = *head;
*head = newnode;
}
void LinkListPopFront(LinkNode** head){//头删(时间复杂度O(N))
if (head == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
LinkNode* cur = *head;
*head = (*head)->next;
DestroyNode(cur);
return;
}
LinkNode* LinkListFind(LinkNode* head, LinkNodeType to_find){//查找元素在链表的位置
if (head == NULL){
//空链表
return NULL;
}
LinkNode *cur = head;
while (cur){
if (cur->data == to_find){
return cur;
}
cur = cur->next;
}
return NULL;
}
void LinkListInsert(LinkNode* pos, LinkNodeType value){//任意位置插入(pos之后)
if (pos == NULL){ //pos为空就代表链表为空
return;
}
LinkNode *newnode = CreateNode(value);
newnode->next = pos->next;
pos->next = newnode;
}
void LinkListInsertBefore(LinkNode** head, LinkNode* pos, LinkNodeType value){//任意位置插入(pos之前)
if (head == NULL || pos == NULL){
//非法输入
return;
}
if (*head == pos){//要插的位置在头结点处,调用头插
LinkListPushFront(head, value);
return;
}
LinkNode* cur = *head;
for (; cur != NULL; cur = cur->next){//pos给的值不一定指向链表中的某个节点,所以要双重判断
if (cur->next == pos){
break;
}
}
if (cur == NULL){ //需知道是哪种情况导致的循环结束
return;
}
LinkListInsert(cur, value);
}
void LinkListErase(LinkNode** head, LinkNode* pos){//删除指定位置的元素
if (head == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
if (pos == *head){
LinkListPopFront(head);
return;
}
LinkNode *cur = *head;
while (cur){
if (cur->next == pos){
cur->next = pos->next;//使pos的前一个元素指向后一个元素,架空pos
DestroyNode(pos);
}
cur = cur->next;
}
return;
}
//为了避免遍历,使用以下方法,但判断pos是否是有效位置与不遍历冲突
void LinkListErase2(LinkNode** head, LinkNode* pos){//删除指定位置的元素(移形换位)
if (head == NULL || pos == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
if (pos->next == NULL){//最后一个节点不能用下一个节点赋值删除,只能调用尾删
LinkListPopBack(head);
return;
}
pos->data = pos->next->data;//->也是解引用,在使用之前必须判断是否为空
LinkNode* to_erase = pos->next;//在删除之前保存要删除值的节点,否则没办法释放内存
pos->next = to_erase->next;
DestroyNode(to_erase);
}
void LinkListRemove(LinkNode** head, LinkNodeType to_delete){//删除指定值的元素
if (head == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
LinkNode* cur = *head;
LinkListErase(head, (LinkListFind(*head, to_delete)));//调用删除函数,在删除函数里调用查找函数查找要删除元素的下标
}
void LinkListRemoveAll(LinkNode** head, LinkNodeType to_delete){  //删除所有指定的元素 
if (head == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
while (1){
LinkNode* pos = LinkListFind(*head, to_delete);
if (pos == NULL){//没找着 说明已经删完了
break;
}
LinkListErase(head, pos);
}
return;
}
int LinkListEmpty(LinkNode* head){//判断链表是否为空
int i = 1;                  
if (head == NULL){
return i;
}
return 0;
}
//{
// return (head == NULL) ?  1 : 0;//三目运算符
//}
size_t LinkListSize(LinkNode* head){//求链表元素的个数
if (head == NULL){
//非法输入
return 0;
}
LinkNode* cur = head;
size_t count = 0;
for (; cur != NULL; cur = cur->next){
if (cur != NULL){
count++;
}
}
return count;
}
void LinkListReversePrint(LinkNode* head){//逆序打印单链表
if (head == NULL){
//空链表
return;
}
else{
LinkListReversePrint(head->next);//递归实现
printf("[%c|%p]", head->data, head);
}
}
void LinkListInsertBefore2(LinkNode** head, LinkNode* pos, LinkNodeType value){//不允许便利链表,在pos之前插入
if (head == NULL || pos == NULL){
//非法输入
return;
}
LinkNode* newnode = CreateNode(pos->data);//先插在pos之后,再修改里面的值
newnode->next = pos->next;
pos->next = newnode;
pos->data = value;
}
LinkNode* JosephCycle(LinkNode* head, size_t food){//约瑟夫环(把下一个节点赋给要删除的节点,再删除下一个节点)
if (head == NULL){
//非法输入
return NULL;
}
if (food == 0){
//非法输入
return NULL;
}


LinkNode* cur = head;
while (cur!=cur->next){//循环的结束条件:最后一个元素的next指向自己
size_t i = 0;
for (; i < food - 1; i++){
cur = cur->next;
}
printf("每次被吃掉的元素:[%c ]\n", cur->data);
LinkNode* to_erase = cur->next;//cur->data是要被吃掉的元素,把后一个节点to_erase的值赋给cur,删掉to_erase,再cur的next指向to_erase的next
cur->data = to_erase->data;//不用考虑解引用的问题,环形链表不存在下一个指向空的问题
cur->next = to_erase->next;
DestroyNode(to_erase);
}
return cur;
}
void LinkListReverse(LinkNode** head){//单链表逆置
if (head == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
LinkNode* cur = *head;
cur = cur->next;
(*head)->next = NULL;//将最后一个节点的next置空
while (cur){
LinkNode* tmp = cur;
cur = cur->next;
tmp->next = *head;
*head = tmp;
}
}
void LinkListReverse2(LinkNode** head){//单链表逆置(删掉元素,使其头插)
if (head == NULL){
//非法输入
return;
}
if (*head == NULL){
//空链表
return;
}
LinkNode* cur = *head;
while (cur->next != NULL){//删除head->next->data,再使其指向head。head指针虽然没有移动,但指向的内容改变了,所以要使用二级指针
LinkNode* to_delete = cur->next;
cur->next = to_delete->next;
to_delete->next = *head;
*head = to_delete;
}
}
void swap(LinkNodeType* a, LinkNodeType* b){
LinkNodeType tmp = *a;
*a = *b;
*b = tmp;
}
void LinkListBubbleSort(LinkNode* head){//单链表的冒泡排序
if (head == NULL){
//非法输入
return;
}
LinkNode* step = head;
LinkNode* tail = NULL;
for (; step != NULL; step = step->next){  //循环的趟数
LinkNode* cur = head;    //每冒完一趟重置cur,将初始化放在内部
for (; cur->next != tail; cur = cur->next){ //循环的过程,每次将最大元素tail->data冒到最后,更新tail
if (cur->data > cur->next->data){
swap(&cur->data, &cur->next->data);
}
}
tail = cur;
}
}
LinkNode* LinkListMerge(LinkNode* head1, LinkNode* head2){// 将两个有序链表, 合并成一个有序链表 
if (head1 == NULL){
return head2;
}
if (head2 == NULL){
return head1;
}
LinkNode* cur1 = head1;
LinkNode* cur2 = head2;
LinkNode* newhead = NULL;
LinkNode* newtail = NULL;
while (cur1 != NULL && cur2 != NULL){
if (cur1->data <= cur2->data){
if (newhead == NULL){
newhead = newtail = cur1;//若cur1中的值小于cur2,将较小值赋给新头结点
}
else{
newtail->next = cur1;
newtail = newtail->next;//移动newtail,直到让其指向最后一个
}
cur1 = cur1->next;
}else if (cur1->data > cur2->data){
if (newhead == NULL){
newhead = newtail = cur2;
}else{
newtail->next = cur2;
newtail = newtail->next;
}
cur2 = cur2->next;
}
}
if (cur1 != NULL){  //比较完元素,对剩余的元素进行处理
newtail->next = cur1;
}
else{
newtail->next = cur2;//若同时为空,newtail->next也为空
}
return newhead;
}
LinkNode* FindMidNode(LinkNode* head){//查找链表中间节点,只遍历一次
if (head == NULL){
//非法输入
return NULL;
}
LinkNode* slow = head;
LinkNode* fast = head;
while ( fast != NULL && fast->next != NULL){ //优先判断fast是否为空
slow = slow->next;
fast = fast->next->next;// 快指针走两步,慢指针走一步,快指针到结尾处,慢指针刚好到中间
}
return slow;
}
LinkNode* FindLastKNode(LinkNode* head, size_t K){//找到倒数第k个节点,只遍历一次
if (head == NULL){
//非法输入
return NULL;
}
LinkNode* slow = head;
LinkNode* fast = head;
size_t i = 0;
for (; i < K-1 && fast != NULL; i++){   //先让fast走k步,再让fast和slow一起走
fast = fast->next;
}
if (i < K-1){
//链表节点数小于K,直接返回NULL
return NULL;
}
    while (fast != NULL && fast->next != NULL){ 
slow = slow->next;
fast = fast->next;
}
return slow;
}
void EraseLastKNode(LinkNode** head, size_t K){  //删除倒数第K个节点
if (head == NULL){
//非法输入
return; 
}
if (*head == NULL){
//空链表
return;
}
size_t size = LinkListSize(*head);//拿到链表总长度
if (size == K){
//要删除的是头节点
LinkListPopFront(head);
}
if (size < K){
//要删除的元素不存在
return;
}
size_t i = 0;  
LinkNode* cur = *head;
for (; i < size - (K + 1); i++){  //cur为要删除节点的前一个节点
cur = cur->next;
}
LinkNode* to_delete = cur->next;
cur->next = to_delete->next;
DestroyNode(to_delete);
}
LinkNode* HasCycle(LinkNode* head){//判断链表是否有环,带环返回他们的相遇点
if (head == NULL){
//非法输入
return NULL;
}
LinkNode* slow = head;
LinkNode* fast = head;
while (fast != NULL && fast->next != NULL){
//在环内每走一步,快慢指针的差距就会减小一步,快慢指针最大距离就是环的长度
//时间复杂度为N(慢指针的步数:环外的步数+环内的步数)
fast = fast->next->next;
slow = slow->next;
if (slow == fast){  //带环的链表 fast的绝对位移大于slow时总会相遇
return fast;//直接返回相遇点
}
}
return NULL;
}
size_t GetCycleLen(LinkNode* head){ //如果链表带环, 求出环的长度
if (head == NULL){
//非法输入
return 0;
}
LinkNode* meet = HasCycle(head);//求出快慢指针的相遇点
if (meet == NULL){
//不带环的链表
return 0;
}
LinkNode* cur = meet;
size_t count = 1;
while (cur->next != meet){ //循环在meet的前一个位置停止,少加一次,count从1开始数
cur = cur->next;
count++;
}
return count;
}
LinkNode* GetCycleEntry(LinkNode* head){ //如果链表带环, 求出环的入口
if (head == NULL){
//非法输入
return NULL;
}
LinkNode* ret = HasCycle(head);
if (ret == NULL){
//链表没有环
return NULL;
}
LinkNode* meet = HasCycle(head);//从head到入口的距离等于相遇点到入口的距离(与指针快慢无关,取决于位移)
LinkNode* fast = head; 
LinkNode* slow = meet;
while (fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
LinkNode* HasCross(LinkNode* head1, LinkNode* head2){//判定两个链表是否相交, 并求出交点 
if (head1 == NULL||head2 ==NULL){
return NULL;
}
//判断两个不带环的链表是否相交
//谁长让谁先走size1和size2的相差长度,然后再一起走,相遇时就是链表交点
size_t size1 = LinkListSize(head1);
size_t size2 = LinkListSize(head2);
size_t i = 0;
LinkNode* cur1 = head1;
LinkNode* cur2 = head2;
if (size1 > size2){
for (; i < size1 - size2; i++){
cur1 = cur1->next;
}
}else{
for (; i < size2 - size1; i++){
cur2 = cur2->next;
}
}
//此时cur1和cur2已经同步了
while (cur1 != cur2){  //即使cur1,cur2相等且同时指向NULL,返回cur1这个空指针也是符合的
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}
LinkNode* CrossIn(LinkNode* head1, LinkNode* head2){//两个带环链表交点在环上(入口点不同)
if (head1 == NULL || head2 == NULL){
//非法输入
return NULL;
}
LinkNode* entry1 = GetCycleEntry(head1);
LinkNode* entry2 = GetCycleEntry(head2);
if (entry1 == NULL&&entry2 == NULL ){
return NULL;
}
if (entry1 == entry2){
//入口点相等,返回NULL
return NULL;
}
LinkNode* cur1 = entry1;
LinkNode* cur2 = entry2;
for (; cur1 != NULL; cur1 = cur1->next){
//从一个的入口点能到另一个环的入口点,这个交点就是链表的交点
if (cur1 == cur2){
return cur1;
}
}
return NULL;
}
int HasCrossWithCycle(LinkNode* head1, LinkNode* head2){
if (head1 == NULL||head2 == NULL){
return 0;
}
LinkNode* entry1 = GetCycleEntry(head1);
LinkNode* entry2 = GetCycleEntry(head2);
if (entry1 == NULL && entry2 == NULL){
//两个链表不带环
return HasCross(head1, head2) != NULL ? 1:0;
}
else if (entry1 != NULL && entry2 != NULL){
//两个链表带环
if (entry1 == entry2){
//入口相等,交点在环外
return 1;
}
else{
//入口不等,交点在环上
CrossIn(entry1, entry2);
return CrossIn(head1, head2) != NULL ? 1:0;
}
}
else{
//一个带环一个不带环,一定不相交,直接返回NULL
return 0;
}
}
LinkNode* UnionSet(LinkNode* head1, LinkNode* head2){//返回交集的新链表
if (head1 == NULL||head2 == NULL){
return NULL;
}
LinkNode* cur1 = head1;
LinkNode* cur2 = head2;
LinkNode* newhead = NULL;
LinkNode* newtail = NULL;
while (cur1 != NULL && cur2 != NULL){
if (cur1->data < cur2->data){
cur1 = cur1->next;
}else if (cur1->data > cur2->data){
cur2 = cur2->next;
}else{
//cur1->data=cur2->data
LinkNode* newnode = CreateNode(cur1->data);
if (newhead == NULL){
newhead = newtail = newnode;
}else{
newtail->next = newnode;
newtail = newtail->next;
}
cur1 = cur1->next;
cur2 = cur2->next;
}
}
return newhead;
}
ComplexNode* CreateComplexNode(LinkNodeType value){
ComplexNode* newnode = (ComplexNode*)malloc(sizeof(ComplexNode));
newnode->data = value;
newnode->next = NULL;
newnode->random = NULL;
return newnode;
}
size_t Diff(ComplexNode* src, ComplexNode* dst){  //求每个random指针相对于head的偏移步数
if (src == NULL || dst == NULL){
return (size_t)-1;//无符号长整形-1是非常大的数,可以用来表示找不到
}
size_t count = 0;
while (src != NULL){ //src跳出循环的两种情况:找到了dst,返回偏移量。走到NULL还没找到,返回(size)-1
if (src == dst){
return count;
}
count++;
src = src->next;
}
return (size_t)-1;
}
ComplexNode* Step(ComplexNode* pos,size_t offset){//从pos开始走offset步所在的位置
size_t i = 0;
for (; i < offset; i++){
if (pos == NULL){
return NULL;
}
pos = pos->next;
}
return pos;
}
ComplexNode* CopyComplex(ComplexNode* head){//拷贝复杂链表
if (head == NULL){
//空链表
return NULL;
}
ComplexNode* newhead = NULL;
ComplexNode* newtail = NULL;
ComplexNode* cur = head;
//复制链表
for (; cur != NULL; cur = cur->next){  
ComplexNode* newnode = CreateComplexNode(cur->data);
if (newhead == NULL){
newhead = newtail = newnode;
}else{
newtail->next = newnode;
newtail = newtail->next;
}
}
ComplexNode* newcur = newhead;
//使cur和newcur保持同步,同时遍历
for (cur = head; cur != NULL && newcur != NULL; cur = cur->next,newcur=newcur->next){//循环到这里,cur已经指向NULL了,必须重置cur的指向
if (cur->random == NULL){
newcur->random = NULL;
continue;
}
size_t offset = Diff(head, cur->random);//求每个random指针相对于head的偏移步数
newcur->random = Step(newhead, offset); //根据偏移量修改新链表的random指针
}
return newhead;
}
ComplexNode* CopyComplex2(ComplexNode* head){//拷贝复杂链表
ComplexNode* cur = head;
//遍历旧链表,给每一个节点都创建一个对应的节点,并且将这个节点插入到旧节点之后
for (; cur != NULL; cur = cur->next->next){
ComplexNode* newnode = CreateComplexNode(cur->data);
newnode->next = cur->next;
cur->next = newnode;
}
//遍历链表,更新每个新节点的random指针
for (cur = head; cur != NULL; cur = cur->next->next){
if (cur->random == NULL){
cur->next->random = NULL;
continue;
}
cur->next->random = cur->random->next;
}
//再遍历链表,把新节点拆下来,组装成新链表
ComplexNode* newhead = NULL;
ComplexNode* newtail = NULL;
for (cur = head; cur != NULL; cur = cur->next){
ComplexNode* to_delete = cur->next;
cur->next = to_delete->next;
if (newhead == NULL){
newhead = newtail = to_delete;
}
else{
newtail->next = to_delete;
newtail = newtail->next;
}
}
return newhead;

}


test.c

#include "linklist.h"
#define TEST_HEADER printf("\n==================%s===================\n",__FUNCTION__)
void TestInit(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
}
void TestPushBack(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPrintChar(head,"尾部插入四个元素");
}
void TestPopBack(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPopBack(&head);
LinkListPrintChar(head, "对空链表进行删除");
LinkListPushBack(&head, 'a');
LinkListPopBack(&head);
LinkListPrintChar(head, "对只有一个元素的链表进行删除");
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPopBack(&head);
LinkListPopBack(&head);
LinkListPrintChar(head, "尾部删除两个元素");
}
void TestPushFront(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushFront(&head, 'a');
LinkListPushFront(&head, 'b');
LinkListPushFront(&head, 'c');
LinkListPushFront(&head, 'd');
LinkListPushFront(&head, 'e');
LinkListPrintChar(head, "头部插入四个元素");
}
void TestPopFront(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPopFront(&head);
LinkListPrintChar(head, "对空链表进行删除");
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPopFront(&head);
LinkListPopFront(&head);
LinkListPrintChar(head, "头部删除两个元素");
}
void TestFind(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPrintChar(head, "查找b元素的位置");
LinkNode* cur = LinkListFind(head,'b');
printf("%p\n", cur);
}
void TestInsert(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkNode* pos = head->next;
LinkListInsert(pos, 'x');
LinkListPrintChar(head, "在b之后插入一个元素'x'");
}
void TestInsertBefore(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkNode* pos1 = head;
LinkListInsertBefore(&head, pos1, 'x');
LinkListPrintChar(head, "在a之前插入一个元素'x'");
LinkNode* pos2 = head->next->next;     //头指针的位置已改变
LinkListInsertBefore(&head, pos2, 'y');
LinkListPrintChar(head, "在b之前插入一个元素'y'");
}
void TestErase(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkNode* pos1 = head;
LinkListErase(&head, pos1);
LinkListPrintChar(head, "删除元素'a'");
LinkNode* pos2 = head->next->next->next;     //头指针的位置已改变
LinkListErase(&head, pos2);
LinkListPrintChar(head, "删除元素'e'");
}
void TestErase2(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkNode* pos1 = head;
LinkListErase2(&head, pos1);
LinkListPrintChar(head, "删除元素'a'");
LinkNode* pos2 = head->next->next->next;     //头指针的位置已改变
LinkListErase2(&head, pos2);
LinkListPrintChar(head, "删除元素'e'");
}
void TestRemove(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListRemove(&head, 'a');
LinkListPrintChar(head, "删除元素'a'");
LinkListRemove(&head, 'c');
LinkListPrintChar(head, "删除元素'c'");
}
void TestRemoveAll(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListRemoveAll(&head, 'd');
LinkListPrintChar(head,"删除所有元素d");
}
void TestEmpty(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListEmpty(head);
int i = LinkListEmpty(head);
printf("i=%d\n", i);
LinkListPrintChar(head, "判断链表是否为空");
}
void TestSize(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListSize(head);
size_t count = LinkListSize(head);
printf("count=%lu\n", count);
LinkListPrintChar(head, "求链表元素的个数");
}
void TestReversePrint(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPrintChar(head, "链表逆序打印");
}
void TestInsertBefore2(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkNode* pos = head->next;
LinkListInsertBefore2(&head,pos, 'x');
LinkListPrintChar(head, "不遍历链表在b之前插入一个元素'x'");
}
void TestJosephCycle(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPushBack(&head, 'f');
LinkListPushBack(&head, 'g');
LinkListPushBack(&head, 'h');
LinkNode* pos = LinkListFind(head, 'h');
pos->next = head;
pos = JosephCycle(head,5);
printf("最后剩余的元素:[%c ]\n", pos->data);
//不能用LinkListPrintChar打印函数。打印条件:最后一个节点的下一个为空时。而约瑟夫环的最后一个的下一个节点指向头节点
}
void TestReverse(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListReverse(&head);
LinkListPrintChar(head, "逆置链表");
}
void TestReverse2(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListReverse2(&head);
LinkListPrintChar(head, "逆置链表2");
}
void TestBubbleSort(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListBubbleSort(head);
LinkListPrintChar(head, "对单链表进行冒泡排序");
}
void TestMerge(){
TEST_HEADER;
LinkNode* head1;
LinkNodeInit(&head1);
LinkListPushBack(&head1, 'a');
LinkListPushBack(&head1, 'c');
LinkListPushBack(&head1, 'e');
LinkListPushBack(&head1, 'g');
LinkNode* head2;
LinkNodeInit(&head2);
LinkListPushBack(&head2, 'b');
LinkListPushBack(&head2, 'd');
LinkListPushBack(&head2, 'f');
LinkListPushBack(&head2, 'h');
LinkNode* newhead = LinkListMerge(head1,head2);
LinkListPrintChar(newhead, "将两个有序链表合成一个新的有序链表");
}
void TestFindMidNode(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPrintChar(head, "尾插四个元素");
LinkNode* mid = FindMidNode(head);
printf("mid value expect c,actual %c", mid->data);
}
void TestFindLastKNode(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPrintChar(head, "尾插四个元素");
LinkNode* pos = FindLastKNode(head ,2);
printf("K value expect a,actual %c", pos->data);
}
void TestEraseLastKNode(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPrintChar(head, "尾插四个元素");
EraseLastKNode(&head,2);
LinkListPrintChar(head, "删除倒数第2个元素");
}
void TestHasCycle(){
TEST_HEADER;
LinkNode* head;
不带环时
//LinkNodeInit(&head);
//LinkListPushBack(&head, 'a');
//LinkListPushBack(&head, 'b');
//LinkListPrintChar(head, "尾插五个元素");
//HasCycle(head);
//LinkNode* ret1 = HasCycle(head);
//printf("expect result is NULL ,actual is %p\n", ret1);


//快指针的绝对位移小于慢指针时
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkListPrintChar(head, "尾插五个元素");
LinkNode* pos1 = LinkListFind(head, 'e');
LinkNode* pos2 = LinkListFind(head, 'd');
pos1->next = pos2;
HasCycle(head);
LinkNode* ret2 = HasCycle(head);
printf("expect result is not NULL ,actual is %p\n", ret2);


快指针的绝对位移大于慢指针时
//LinkNodeInit(&head);
//LinkListPushBack(&head, 'a');
//LinkListPushBack(&head, 'b');
//LinkListPushBack(&head, 'c');
//LinkListPushBack(&head, 'd');
//LinkListPushBack(&head, 'e');
//LinkListPrintChar(head, "尾插五个元素");
//LinkNode* pos = LinkListFind(head, 'e');
//pos->next = head;
//HasCycle(head);
//LinkNode* ret3 = HasCycle(head);
//printf("expect result is not NULL ,actual is %p\n",ret3);
}
void TestGetCycleLen(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkNode* pos1 = LinkListFind(head, 'e');
LinkNode* pos2 = LinkListFind(head, 'c');
pos1->next = pos2;
GetCycleLen(head);
size_t ret = GetCycleLen(head);
printf("expect cyclclen is 3,actual is %lu\n", ret);
}
void TestGetCycleEntry(){
TEST_HEADER;
LinkNode* head;
LinkNodeInit(&head);
LinkListPushBack(&head, 'a');
LinkListPushBack(&head, 'b');
LinkListPushBack(&head, 'c');
LinkListPushBack(&head, 'd');
LinkListPushBack(&head, 'e');
LinkNode* pos1 = LinkListFind(head, 'e');
LinkNode* pos2 = LinkListFind(head, 'c');
pos1->next = pos2;
LinkNode* ret = GetCycleEntry(head);
printf("expect entry is c,actual is %c\n", ret->data);
}
void TestHasCross(){
TEST_HEADER;
LinkNode* head1;
LinkNodeInit(&head1);
LinkListPushBack(&head1, 'a');
LinkListPushBack(&head1, 'b');
LinkListPushBack(&head1, 'c');
LinkListPushBack(&head1, 'd');
LinkListPushBack(&head1, 'e');


LinkNode* head2;
LinkNodeInit(&head2);
LinkListPushBack(&head2, 'x');
LinkListPushBack(&head2, 'y');
LinkListPushBack(&head2, 'd');
LinkListPushBack(&head2, 'e');
LinkNode* pos1 = LinkListFind(head1, 'd');
LinkNode* pos2 = LinkListFind(head2, 'd');
pos2->next = pos1;
LinkNode* cross = HasCross(head1,head2);
printf("expect cross is d,actual is %c", cross->data);
}
void TestCrossIn(){
TEST_HEADER;
LinkNode* head1;
LinkNodeInit(&head1);
LinkListPushBack(&head1, 'a');
LinkListPushBack(&head1, 'b');
LinkListPushBack(&head1, 'c');
LinkListPushBack(&head1, 'd');
LinkListPushBack(&head1, 'e');
LinkNode* cur1 = LinkListFind(head1, 'b');
LinkNode* cur2 = LinkListFind(head1, 'e');
cur2->next = cur1;


LinkNode* head2;
LinkNodeInit(&head2);
LinkListPushBack(&head2, 'x');
LinkListPushBack(&head2, 'y');
LinkListPushBack(&head2, 'd');
LinkListPushBack(&head2, 'e');
LinkNode* pre1 = LinkListFind(head2, 'd');
LinkNode* pre2 = LinkListFind(head2, 'e');
pre2->next = pre1;


LinkNode* pos1 = LinkListFind(head1, 'd');
LinkNode* pos2 = LinkListFind(head2, 'd');
pos2->next = pos1;
LinkNode* cross = CrossIn(head1, head2);
printf("expect cross is d,actual is %c", cross->data);
}
void TestHasCrossWithCycle(){
TEST_HEADER;
LinkNode* head1;
LinkNodeInit(&head1);
LinkListPushBack(&head1, 'a');
LinkListPushBack(&head1, 'b');
LinkListPushBack(&head1, 'c');
LinkListPushBack(&head1, 'd');
LinkListPushBack(&head1, 'e');
LinkNode* cur1 = LinkListFind(head1, 'b');
LinkNode* cur2 = LinkListFind(head1, 'e');
cur2->next = cur1;


LinkNode* head2;
LinkNodeInit(&head2);
LinkListPushBack(&head2, 'x');
LinkListPushBack(&head2, 'y');
LinkListPushBack(&head2, 'd');
LinkListPushBack(&head2, 'e');
LinkNode* pre1 = LinkListFind(head2, 'd');
LinkNode* pre2 = LinkListFind(head2, 'e');
pre2->next = pre1;


LinkNode* pos1 = LinkListFind(head1, 'd');
LinkNode* pos2 = LinkListFind(head2, 'd');
pos2->next = pos1;
int cross = HasCrossWithCycle(head1, head2);
printf("expect cross is 1,actual is %d", cross);
}
void TestUnionSet(){
TEST_HEADER;
LinkNode* head1;
LinkNodeInit(&head1);
LinkListPushBack(&head1, 'a');
LinkListPushBack(&head1, 'c');
LinkListPushBack(&head1, 'd');
LinkListPushBack(&head1, 'f');
LinkListPrintChar(head1, "链表1");


LinkNode* head2;
LinkNodeInit(&head2);
LinkListPushBack(&head2, 'a');
LinkListPushBack(&head2, 'b');
LinkListPushBack(&head2, 'c');
LinkListPushBack(&head2, 'd');
LinkListPrintChar(head2, "链表2");


LinkNode* newhead = UnionSet(head1, head2);
LinkListPrintChar(newhead, "两个有序链表的交集");
}
void TestCopyComplex(){
TEST_HEADER;
ComplexNode* a = CreateComplexNode('a');
ComplexNode* b = CreateComplexNode('b');
ComplexNode* c = CreateComplexNode('c');
ComplexNode* d = CreateComplexNode('d');
a->next = b;
b->next = c;
c->next = d;
d->next = NULL;
a->random = c;
b->random = a;
c->random = NULL;
d->random = d;
//ComplexNode* newhead = CopyComplex(a);
ComplexNode* newhead = CopyComplex2(a);
printf("newhead:%p\n", newhead);


}
int main(){
TestInit();
TestPushBack();
TestPopBack();
TestPushFront();
TestPopFront();
TestFind();
TestInsert();
TestInsertBefore();
TestErase();
TestErase2();
TestRemove();
TestRemoveAll();
TestEmpty();
TestSize();
TestReversePrint();
TestInsertBefore2();
TestJosephCycle();
TestReverse();
TestReverse2();
TestBubbleSort();
TestMerge();
TestFindMidNode();
TestFindLastKNode();
TestEraseLastKNode();
TestHasCycle();
TestGetCycleLen();
TestGetCycleEntry();
TestHasCross();
TestCrossIn();
TestHasCrossWithCycle();
TestUnionSet();
TestCopyComplex();
getchar();
system("pause");
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值