一、基本操作
先定义一个结构体类型
#define DataType int
typedef struct LinkList{
DataType Data; //数据域
LinkList * Next; //指针域
}LinkList;
1、链表初始化
/** @funcation:
* Create_LinkList:创建一个链表
* @param:
* node_number:传入创建的节点数量
* @return:
* 返回链表的head头指针
*/
LinkList* Create_LinkList(int node_number){
LinkList * head, *node, *end;
head = (LinkList *)malloc(sizeof(LinkList));
end = head; //此处可能有点绕,大家仔细看一下
while(node_number--){
node = (LinkList *)malloc(sizeof(LinkList));
scanf("%d",&node->Data);
end->Next = node; //创建的节点接在最后一个节点的后面
end = node; //将end节点指向当前链表的最后一个节点
}
end->next = NULL;
return head;
}
2、插入某个节点
/** @funcation:
* Insert_Node:插入一个节点
* @param:
* List:传入需要插入节点的链表
* @return:
* 返回链表的head头指针
*/
LinkList* Insert_Node(LinkList* List){
int num = 0;
DataType data = 0;
scanf("%d%d",&num,&data);//依次输入需要在第几个节点后面插入数据和插入的数据data
LinkList* head = List;
while((num--)&&(List != NULL))
List = List->Next;
if(List->Next != NULL){
LinkList* Node = (LinkList*)malloc(sizeof(LinkList));//申请一段堆内存空间给节点使用
scanf("%d",&Node->Data);//输入需要插入节点的数据域
Node->Next = List->Next;//将当前List的指针域所指向的下一个节点赋值给Node的指针域,让Node的指针域也去指向当前位置的下一个节点
List-Next = Node;//让原先指向下一个节点的指针域现在指向刚创建的这个节点,最后,这个节点就成功的插入进去了
}
else{
printf("节点不存在\n");
return NULL;
}
return head;
}
3、删除某个节点
/** @funcation:
* Delete_Node:删除一个节点
* @param:
* List:传入需要删除节点的链表
* @return:
* 返回链表的head头指针
*/
LinkList* Insert_Node(LinkList* List){
int num = 0;
scanf("%d",&num);//依次输入需要在第几个节点后面删除节点
LinkList* head = List;
LinkList* Tmp_Node;
while((num--)&&(List != NULL))
List = List->Next;
if((List->Next)->Next != NULL){
Tmp_Node = List->Next;//保存当前预删除的节点的存储空间的起始地址
List->Next = (List->Next)->Next;//将当前节点的指针域指向当前节点的下下个节点,这样,当前节点原先的下一个节点就已经被移出去了,但现在我们还要释放内存,防止内存泄漏
free(Tmp_Node);//释放内存
}
else{
printf("节点不存在\n");
return NULL;
}
return head;
}
4、查找某个节点
/** @funcation:
* Find_Node:查找某个节点
* @param:
* List:需要被查找节点的链表
* @return:
* 失败返回-1,成功返回节点查找到的位置
*/
int Find_Node(LinkList* List){
int num = 0;
DataType data = 0;
scanf("%d",&data);
while(List->Next != NULL){
List = List->Next;
num++;
if(List->Data == data)
return num;
}
return -1;
}
5、修改节点的数据域
/** @funcation:
* Change_Node:修改某个节点的数据域
* @param:
* List:需要被修改节点的链表
* @return:
* 失败返回-1,成功返回1
*/
int Find_Node(LinkList* List){
int num = 0;
DataType data = 0;
scanf("%d%d",&num,&data);
while((num--)&&(List->Next != NULL))
List = List->Next;
if(num == 0){ //如果while循环因为num==0退出,那我们继续进行下一步
List->Data = data;
return 1;
}
if(Link->Next == NULL)//如果while循环因为LinkList == NULL退出,那我们返回-1
return -1;
}
6、遍历所有节点
/** @funcation:
* Print_AllNode:遍历所有节点
* @param:
* List:需要遍历的链表
* @return:
* 失败返回-1,成功返回1
*/
int Print_AllNode(LinkList* List){
while(List != NULL){
printf("%d ",List->Data);
List = List->Next;
}
return 1;
}
二、链表反转
/** @funcation:
* ListReverse:链表反转
* @param:
* List:需要反转的链表
* @return:
* 返回反转后的头节点
*/
LinkList* ListReverse(LinkList* List){
LinkList *p, *q, *r;
p = List;
q = p->Next;
r = q->Next;
p->Next = NULL;
while(r){
q->Next = p;
p = q;
q = r;
r = q->Next;
}
q->Next = p;
return q;
}
三、判断链表是否有环
定义两个指针slow、fast,slow指针每次移动一个节点位置,fast指针每次移动两个节点位置,如果他们能相遇到同一节点,证明链表有环
/** @funcation:
* has_Cycle:判断链表是否有环
* @param:
* List:需要判断的链表
* @return:
* 有环返回true,无环返回false
*/
bool has_Cycle(LinkList* List){
LinkList* slow, *fast;
slow = List;
fast = List;
while(fast){
if(fast->Next == NULL)
return false;
slow = slow->Next;
fast = (fast->Next)->Next;
if(slow == fast)
return true;
}
return flase;
}