头文件 “Link.h”
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct Node
{
int data;
struct Node* next;
}*pList,*pNode,*pLinkNode;
void ListToheadFromLastD(pList plist); //递归
void ListToheadFromLast(pList* pplist); //从尾到头打印,非递归
void EraseNotTailNode(pList* pplist,pNode pos); //删除一个无头单链表的非尾节点
void InsertNodeNoHead(pList* pplist,pNode pos,int d); //在一个无头单链表的一个节点前插入一个节点
void JosephCricle(pList* pplist, int d); //约瑟夫环
void BubbleSort(pList plist); //冒泡排序
void SelectSort(pList plist); //选择排序
void myQuickSort(pList pStart,pList pEnd); //快速排序
pNode AddSort(pList* pplist1, pList* pplist2); //合并两个有序链表,结果依然有序,递归
pNode FindNode(pList plist,int d); //查找单链表的中间节点
pNode FindFromtail(pList plist, int k); //查找单链表倒着数第k个元素
void rmNodeFromTail(pList* pplist, int k); //删除倒数第k个元素
void UnionSet(pList plist1, pList plist2); //求两个已排序单链表中相同的元素
pLinkNode CheckCycle(pList plist); //判断链表是否带环
int GetCircleLength(pLinkNode meet); //求环的长度
pLinkNode GetCycleEntryNode(pList list, pLinkNode meetNode); //求环的入口点
pNode CheckCross(pList list1, pList list2); //判断两个链表是否相交,若相交求交点
pNode PanDuanSuper(pList p1, pList p2); //判断升级版
void DestroyList(pList plist); //销毁链表
pNode BuyNode(int d);
pNode CreatList(pList* pplist, int d); //创建一个连续的连续的链表
void PushBack(pList* pplist, int d); //尾插
void Print(pList plist); //打印
#endif __LINKLIST_H__
1.从尾到头打印单链表(递归)
void ListToheadFromLastD(pList plist) //从尾到头打印,递归
{
pNode cur = plist;
if (plist == NULL)
return;
if (cur->next == NULL)
{
printf("%d->", cur->data);
return;
}
ListToheadFromLastD(cur->next);
printf("%d->", cur->data);
}
2.从尾到头打印单链表
void ListToheadFromLast(pList* pplist) //从尾到头打印,非递归,头插法
{
pNode cur = NULL;
pNode re = NULL;
cur =(*pplist)->next; //cur总是指向tmp的下一个节点
(*pplist)->next = NULL; //将第一个的节点中的指针赋为NULL,当链表的最后一个节点
while (cur)
{
re = cur->next;
cur->next = *pplist;
*pplist = cur;
cur = re;
}
}
3.删除一个无头单链表的非尾节点
void EraseNotTailNode(pList* pplist,pNode pos) //删除一个无头单链表的非尾节点
{
assert(pos != NULL);
pos->data = pos->next->data; //用下一个位置的数据把该位置的数据覆盖掉
pNode del = pos->next;
pos->next = del->next;
free(del);
del = NULL;
}
4.在无头单链表前插入一个节点
void InsertNodeNoHead(pList* pplist,pNode pos,int d) //在一个无头单链表的一个节点前插入一个节点
{
assert(pos != NULL);
DataType tmp = 0;
pNode newNode = BuyNode(d);
newNode->next = pos->next;
pos->next = newNode;
tmp = pos->data; //先插在指定位置的后面,再交换数值
pos->data = newNode->data;
newNode->data = tmp;
}
5.约瑟夫环
void JosephCricle(pList* pplist,int d) //约瑟夫环
{
assert(pplist != NULL);
pNode cur = *pplist;
pNode del = NULL;
pNode flag = NULL;
int i = 0;
while (1)
{
i = d;
if (cur->next == cur)
{
printf("幸存者:%d\n", cur->data);
break;
}
while (--i)
{
flag = cur;
cur = cur->next;
}
printf("杀死:%d\n", cur->data);
del = cur;
flag->next = del->next;
cur = cur->next;
free(del);
}
}
6.冒泡排序
void BubbleSort(pList plist) //冒泡排序
{
assert(plist != NULL);
pNode cur = plist;
pNode flag = NULL; //标记已排完序的最后一个节点
int tmp = 0;
while (cur!=flag)
{
while (cur->next!=flag) //flag控制内层循环
{
if (cur->data > cur->next->data)
{
tmp = cur->data;
cur->data = cur->next->data;
cur->next->data = tmp;
}
cur = cur->next;
}
flag = cur;
cur = plist;
}
}
6.选择排序
void SelectSort(pList plist) //选择排序
{
assert(plist != NULL);
pNode cur = plist;
pNode tell = NULL; //标记最后一个节点
pNode flag = cur; //标记最大元素的节点
int tmp = 0;
while (cur!=tell)
{
int max = cur->data;
while (cur->next != tell)
{
if (max < cur->next->data)
{
max = cur->next->data;
flag = cur->next;
}
cur = cur->next;
}
if (flag != cur)
{
tmp = flag->data;
flag->data = cur->data;
cur->data = tmp;
}
tell = cur;
cur = plist;
flag = cur;
}
}
7.快速排序
void myQuickSort(pList pStart, pList pEnd) //快速排序,pEnd==NULL
{
if (pStart == NULL || pStart == pEnd) //起始节点为空,结束
return;
int key = pStart->data;
pNode cur1 = pStart;
pNode cur2 = cur1->next;
while (cur2 != pEnd)
{
if (cur2->data < key)
{
cur1 = cur1->next;
myswap(&(cur1->data), &(cur2->data));
}
cur2 = cur2->next;
}
myswap(&(pStart->data), &(cur1->data));
pNode flag = cur1;
myQuickSort(pStart, flag);
myQuickSort(flag->next, pEnd);
}
8.查找单链表倒数第k个节点
pNode FindFromtail(pList plist, int k) //查找单链表倒着数第k个元素
{
pNode cur = plist;
pNode flag = plist;
while (cur) //遍历链表
{
int d = k;
flag = cur; //标记节点
while (--d) //遍历k-1次
{
cur = cur->next;
if (cur == NULL) //一旦k大于链表的实际长度时,cur没到k-1次就会出现NULL
return NULL;
}
if (cur->next == NULL) //当遍历第k-1次后,cur的next为空,则flag就为要找的那个元素
return flag;
cur = flag->next; //否则,从头开始下一个
}
return NULL;
}
9.合并两个有序单链表
pNode AddSort(pList* pplist1, pList* pplist2) //合并两个有序链表,结果依然有序,递归
{
pNode pHead = NULL;
if (*pplist1 == NULL)
return *pplist2;
else if (*pplist2 == NULL)
return *pplist1;
if (*pplist1 == NULL && *pplist2 == NULL)
return NULL;
if (((*pplist1)->data) < ((*pplist2)->data))
{
pHead = *pplist1;
pHead->next = AddSort(&((*pplist1)->next), &(*pplist2));
}
else
{
pHead = *pplist2;
pHead->next = AddSort(&(*pplist1), &((*pplist2)->next));
}
return pHead;
}
10.判断链表是否带环
pLinkNode CheckCycle(pList plist) //判断链表是否带环
{
pNode slow = plist;
pNode fast = plist;
while (fast && fast->next)
{
slow = slow->next; //slow一次走一步
fast = fast->next->next; //fast一次走两步
if (fast == slow) //是环,总会相遇
return fast;
}
return NULL; //不是环
}
11.求环的长度
int GetCircleLength(pLinkNode meet) //求环的长度
{
int len = 1;
pNode cur = meet->next; //meet是快慢指针的交点
while (cur!=meet)
{
len++;
cur = cur->next;
}
return len;
}
12.求环的入口点
pLinkNode GetCycleEntryNode(pList plist, pLinkNode meetNode)
//求环的入口点,meetNode是带环时的快慢指针的交点
{
pNode cur = plist;
while (cur != meetNode)
{
cur = cur->next;
meetNode = meetNode->next;
}
return cur;
}
13.求两个环的交点
pNode CheckCross(pList plist1, pList plist2) //判断两个链表是否相交,若相交求交点
{
assert(plist1 != NULL);
assert(plist2 != NULL);
pNode cur1 = plist1;
pNode cur2 = plist2;
int len1 = 1;
int len2 = 1;
int a = 0;
while (cur1->next)
{
len1++;
cur1 = cur1->next;
}
while (cur2->next)
{
len2++;
cur2 = cur2->next;
}
if (cur1 == cur2) //若两个链表的尾地址相同,则相交
{
printf("相交\n");
cur1 = plist1;
cur2 = plist2;
if (len1 < len2) //调整,使cur1指的是长一些的链表
{
cur1 = plist2;
cur2 = plist1;
}
a=abs(len1-len2); //绝对值
while (a--)
{
cur1 = cur1->next; //让长的走a步,使两个链表里交点的距离相等
}
while (cur1 != cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
printf("交点为:%d\n", cur1->data);
return cur1;
}
printf("不相交\n");
return NULL;
}
14.复杂链表的复制
思想:1.先复制节点插到每个节点的后边
2.再复制tmp随机指针,就是原tmp指针的next
3.最后断开成两个链表
#include "ComplexList.h"
//复杂链表的实现
pComplexNode BuyComplexNode(DataType d) //买一个复杂节点
{
pComplexNode newNode = (pComplexNode)malloc(sizeof(struct ComplexNode));
if (newNode)
{
newNode->next = NULL;
newNode->tmp = NULL;
newNode->data = d;
return newNode;
}
perror("the take failer:");
return NULL;
}
void Print(pComplexList p)
{
pComplexNode cur = p;
if (p == NULL)
return;
while (cur)
{
printf("%d-->", cur->data);
cur = cur->next;
}
printf("over\n");
}
pComplexList CopyList(pComplexList p1) //复制复杂链表
{
//先复制链表插入到p1当中
pComplexNode cur = p1;
pComplexNode cur2 = NULL;
pComplexNode p2 = NULL;
pComplexNode flag = NULL;
while (cur)
{
flag = cur->next;
pComplexNode newNode = BuyComplexNode(cur->data);
newNode->next = flag;
cur->next = newNode;
cur = flag;
}
//设置tmp
cur = p1;
while (cur)
{
if (cur->tmp != NULL)
{
cur->next->tmp = cur->tmp->next;
cur = cur->next->next;
}
else
{
cur->next->tmp = NULL;
cur = cur->next->next;
}
}
//断开链表
cur = p1;
p2 = p1->next;
cur2 = p2;
while (cur->next->next)
{
flag = cur->next->next;
cur->next = flag;
cur = flag;
cur2->next = flag->next;
cur2 = cur2->next;
}
cur->next = NULL;
return p2;
}
//销毁链表
void DestroyComplexList(pComplexList p) //销毁链表
{
pComplexNode del = NULL;
while (p)
{
del = p->next;
free(p);
p = del;
}
}