单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
1、链接存储方法
链接方式存储的线性表简称为链表(LinkList)。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
注意:
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
2、链表的结点结构
┌───┬───┐
│data │next │
└───┴───┘
data域--存放结点值的数据域
next域--存放结点的直接后继的地址(位置)的指针域(链域)
//功能
//LinkList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct LinkNode //节点 = 数据 + 指向下一个节点的指针
{
DataType data;
struct LinkNode *next;
}LinkNode,*pLinkNode,*pLinkList;
void InitLinkList(pLinkList* pHead); //初始化链表
void Destroy(pLinkList* pHead); //销毁链表
pLinkNode BuyNode(DataType x); //创建一个节点
void PushBack(pLinkList *pHead, DataType x); //尾插
void PopBack(pLinkList *pHead); //尾删
void PushFront(pLinkList *pHead, DataType x); // 头插
void PopFront(pLinkList *pHead); //头删
void PrintList(pLinkList List); //打印链表
int GetListLength(pLinkList Head); //求取链表长度
pLinkNode Find(pLinkList Head, DataType x); //找指定元素x
void Insert(pLinkList *pHead, pLinkNode pos, DataType x); //在指定位置pos插入指定元素x
void Erase(pLinkList *pHead, pLinkNode pos); //删除指定位置pos元素
void Remove(pLinkList* pHead, DataType x); //删除指定元素x
void RemoveAll(pLinkList* pHead, DataType x); //删除所有的指定元素x
void EraseNotTail(pLinkNode pos); // 删除无头链表的非尾节点
void ReverseList(pLinkNode *pHead); // 逆序链表
void BubbleSort(pLinkList *pHead); //排序链表(冒泡)
void InsertFrontNode(pLinkNode pos, DataType x); //在当前节点前插入一个数据x
pLinkNode Merge(pLinkList list1, pLinkList list2); //合并两个有序链表
pLinkNode JosephCycle(pLinkList* pHead, int num); //约瑟夫环
pLinkNode FindMidNode(pLinkList pHead); //查找链表的中间节点---7
// 删除单链表的倒数第k个节点(k > 1 && k < 链表的总长度)----9
// 时间复杂度O(N)
void DelKNode(pLinkList *pHead, int k);
// 【链表带环问题】-----10
// 判断链表是否带环, 若链表带环则求环的长度和相遇节点,不带环返回-1
pLinkNode CheckCycle(pLinkList pList);
int GetCircleLength(pLinkNode meet);
// 获取环入口点
pLinkNode GetCycleEntryNode(pLinkList list, pLinkNode meetNode);
// 【链表相交问题】
//
// 判断两个链表是否相交,假设两个链表都不带环。
//
int CheckCross(pLinkList list1, pLinkList list2);
//功能实现
//LinkList.c
#include "LinkList.h"
void InitLinkList(pLinkList* pHead) //初始化链表
{
assert(pHead);
*pHead = NULL;
}
void Destroy(pLinkList* pHead) //销毁链表
{
pLinkNode cur = *pHead;
assert(pHead);
if(*pHead == NULL)
{
return;
}
else
{
while(cur)
{
pLinkNode del = cur;
cur = cur->next;
free(del);
del = NULL;
}
}
}
pLinkNode BuyNode(DataType x) //创建一个节点
{
pLinkNode NewNode = (pLinkNode)malloc(sizeof(LinkNode));
NewNode->data = x;
NewNode->next = NULL;
return NewNode;
}
void PushBack(pLinkList *pHead, DataType x) //尾插
{
pLinkNode NewNode = BuyNode(x);
pLinkNode cur = *pHead;
assert(pHead);
if(cur == NULL)
{
*pHead = NewNode;
}
else
{
while(cur->next)
{
cur = cur->next;
}
cur->next = NewNode;
}
}
void PopBack(pLinkList* pHead)//尾删
{
pLinkNode cur = *pHead;
assert(pHead);
//没有节点
if(*pHead == NULL)
{
return;
}
//一个节点
else if((*pHead)->next == NULL)
{
free(*pHead);
*pHead = NULL;
}
//两个及以上
else
{
pLinkNode del;
while(cur->next->next)
{
cur = cur->next;
}
del = cur->next;
cur->next = NULL;
free(del);
del = NULL;
}
}
void PushFront(pLinkList *pHead, DataType x) //头插
{
pLinkNode NewNode = BuyNode(x);
assert(pHead);
if(*pHead == NULL)
{
*pHead = NewNode;
}
else
{
NewNode->next = *pHead;
*pHead = NewNode;
}
}
void PopFront(pLinkList *pHead) //头删
{
assert(pHead);
if(*pHead == NULL)
{
return;
}
else
{
pLinkNode del = *pHead;
*pHead = (*pHead)->next;
free(del);
del = NULL;
}
}
void PrintList(pLinkList List) //打印链表
{
pLinkNode cur = (pLinkNode)List;
printf("List is:");
while(cur)
{
printf("%d->",cur->data);
cur = cur->next;
}
printf("over\n");
}
int GetListLength(pLinkList Head) //求取链表长度
{
int count = 0;
pLinkList cur = Head;
assert(Head);
while(cur)
{
count++;
if(cur->next == NULL)
{
return count;
}
cur = cur->next;
}
return count;
}
pLinkNode Find(pLinkList Head, DataType x) //查找指定元素x的位置
{
pLinkList cur = Head;
assert(Head);
while(cur)
{
if(cur->data == x)
{
return (pLinkNode)cur;
}
cur = cur->next;
}
return NULL;
}
void Insert(pLinkList *pHead, pLinkNode pos, DataType x) //指定位置pos插入元素x
{
pLinkNode cur = *pHead;
pLinkNode NewNode =BuyNode(x);
assert(pHead);
assert(pos);
while(cur->next != pos)
{
cur = cur->next;
}
NewNode->next = cur->next;
cur->next = NewNode;
}
void Erase(pLinkList *pHead, pLinkNode pos) //删除pos位置元素
{
pLinkNode cur = *pHead;
pLinkNode del = NULL;
pLinkNode prev = NULL; //cur的前一个节点
assert(pHead);
assert(pos);
if (cur == NULL)
{
printf("List is empty!!\n");
return;
}
while(cur)
{
del = cur;
if (cur == pos)
{
//没有节点
if(cur == *pHead)
{
*pHead = (*pHead)->next;
}
//一个及以上节点
else
{
prev->next = cur->next;
}
free(del);
del = NULL;
break; //删除完成后,跳出Erase()
}
prev = cur;
cur = cur->next;
}
}
void Remove(pLinkList* pHead, DataType x) //删除元素x
{
pLinkNode cur = *pHead;
pLinkNode del = NULL;
pLinkNode prev = NULL;//cur的前一个节点
assert(pHead);
if(cur == NULL)
{
printf("List is empty!!\n");
return;
}
while(cur)
{
del = cur;
if(cur->data == x)
{
//没有节点
if(cur == *pHead)
{
*pHead = (*pHead)->next;
}
//一个及以上节点
else
{
prev->next = cur->next;
}
free(del);
del = NULL;
break; //只删除一次,删除后跳出Remove()
}
prev = cur;
cur = cur->next;
}
}
void RemoveAll(pLinkList* pHead, DataType x) //删除所有的元素x
{
pLinkNode cur = *pHead;
pLinkNode del = NULL;
pLinkNode prev = NULL; //cur的前一个节点
assert(pHead);
if(cur == NULL)
{
printf("List is empty!!\n");
return;
}
while(cur)
{
del = cur;
if(cur->data == x)
{
//没有节点
if(cur == *pHead)
{
*pHead = (*pHead)->next;
cur = *pHead;
}
//一个及以上节点
else
{
prev->next = cur->next;
cur = prev->next;
}
free(del);
del = NULL;
}
else
{
prev = cur;
cur = cur->next;
}
}
}
void EraseNotTail(pLinkNode pos) // 删除无头链表的非尾节点
{
pLinkNode del = NULL;
assert(pos);
/*替换删除*/
pos->data = pos->next->data; //将要删除节点的数据用他下一个节点的数据进行替换
del = pos->next;
pos->next = del->next;
free(del); //删除下一个节点
del = NULL;
}
void ReverseList(pLinkList* pHead) // 逆序链表
{
pLinkNode cur = *pHead;
pLinkNode prev = NULL;
pLinkNode pNewHead = NULL;
assert(pHead);
if(pHead == NULL) /*空链表*/
{
printf("List is empty!!\n");
return;
}
else if((*pHead)->next == NULL) /*一个节点*/
{
return;
}
else
{
while(cur != NULL)
{
prev = cur;
cur = cur->next;
prev->next = pNewHead;
pNewHead = prev;
}
*pHead = pNewHead; // *pHead指向新的头结点
}
}
void BubbleSort(pLinkList *pHead) //排序链表(冒泡)
{
pLinkNode cur = *pHead;
pLinkNode end = NULL;
assert(pHead);
while(cur != end) //冒泡的次数
{
while(cur && (cur->next != end)) //一次冒泡 ,最大的数放到末尾
{
if(cur->data > cur->next->data) //交换数据
{
DataType tmp = cur->data;
cur->data = cur->next->data;
cur->next->data = tmp;
}
cur = cur->next;
}
end = cur; //记住最大数的位置
cur = *pHead;
}
}
void InsertFrontNode(pLinkNode pos, DataType x) //在当前节点前插入一个数据x
{
pLinkNode NewNode = BuyNode(x);
DataType tmp;
assert(pos);
NewNode->next = pos->next; //替换插入
pos->next = NewNode;
tmp = pos->data; //交换数据
pos->data = NewNode->data;
NewNode->data = tmp;
}
pLinkNode Merge(pLinkList list1, pLinkList list2) //合并两个有序链表
{
pLinkNode NewHead = NULL;
pLinkNode cur = NULL;
if(list1 == list2) //两个链表相等
{
return list1;
}
if((list1 == NULL) && (list2 != NULL))
{
return list2; //list1为空
}
if((list1 != NULL) && (list2 == NULL))
{
return list1; //list2为空
}
/*确定头结点*/
if(list1->data > list2->data)
{
NewHead = list2;
list2 = list2->next;
}
else
{
NewHead = list1;
list1 = list1->next;
}
cur = NewHead;
while((list1) && (list2))
{
if(list1->data > list2->data)
{
cur->next = list2;
list2 = list2->next;
}
else
{
cur->next = list1;
list1 = list1->next;
}
cur = cur->next;
}
/*至少一个链表此时为空,将不为空的连接在新链表的后面*/
if(list1)
{
cur->next = list1;
}
else
{
cur->next = list2;
}
return NewHead;
}
pLinkNode _Merge(pLinkList list1, pLinkList list2) //合并两个有序链表(递归)
{
pLinkNode NewHead = NULL;
if(list1 == list2) //两个链表相等
{
return list1;
}
else if((list1 == NULL) && (list2 != NULL))
{
return list2; //list1为空
}
else if((list1 != NULL) && (list2 == NULL))
{
return list1; //list2为空
}
if(list1->data >list2->data)
{
NewHead = list2;
NewHead->next = _Merge(list1, list2->next); //递归调用
}
else
{
NewHead = list1;
NewHead->next = _Merge(list1->next, list2); //递归调用
}
return NewHead;
}
pLinkNode JosephCycle(pLinkList* pHead, int num) //约瑟夫环
{
pLinkNode del = NULL;
pLinkNode cur = *pHead;
int count = 0;
assert(pHead);
while(1)
{
count = num;
if(cur->next == cur) //结束条件
{
break;
}
while(--count)
{
cur = cur->next;
}
printf("%d ",cur->data);
del = cur->next;
cur->next = del->next;
cur->data = del->data;
free(del);
del = NULL;
}
*pHead = cur;
printf("\n");
return cur;
}
pLinkNode FindMidNode(pLinkList pHead) //查找链表的中间节点
{
pLinkNode Fast = pHead;
pLinkNode Slow = pHead;
assert(pHead);
if(pHead == NULL)
{
printf("List is empty!!\n");
return NULL;
}
while(Fast && Fast->next)
{
Fast = Fast->next->next;
Slow = Slow->next;
}
return Slow;
}
void DelKNode(pLinkList *pHead, int k) //删除单链表的倒数第k个节点(k > 1 && k < 链表的总长度)
{
pLinkNode first = *pHead;
pLinkNode second = *pHead;
pLinkNode del =NULL;
assert(k>1);
//快指针先走k步
while(--k)
{
//判断k是否合法(k小于链表长度)
if(k != 0)
{
if(first == NULL)
{
printf("Please enter legal (k)!!\n");
return;
}
}
first = first->next;
}
//快慢指针一起走
while(first && first->next)
{
first = first->next;
second = second->next;
}
//替换删除
del = second->next;
second->data = del->data;
second->next = del->next;
free(del);
del = NULL;
}
pLinkNode CheckCycle(pLinkList pList) //判断链表是否带环
{
pLinkNode Fast = pList;
pLinkNode Slow = pList;
assert(pList);
while(Fast && Fast->next)
{
Fast = Fast->next->next;
Slow = Slow->next;
if(Fast == Slow) //判断是否带环
{
return Fast;
}
}
return NULL;
}
int GetCircleLength(pLinkNode meet) //链表带环则求环的长度和相遇节点,不带环返回-1
{
pLinkNode cur = meet;
int count = 0;
do
{
cur = cur->next;
count++;
}while(cur != meet);
return count;
}
pLinkNode GetCycleEntryNode(pLinkList list, pLinkNode meetNode) // 获取环入口点
{
pLinkNode Entry = list;
pLinkNode Meet = meetNode;
while(Entry != Meet)
{
Entry = Entry->next;
Meet = Meet->next;
}
return Entry;
}
// 【链表相交问题】
//
//判断两个链表是否相交,假设两个链表都不带环。
//
int CheckCross(pLinkList list1, pLinkList list2)
{
pLinkNode first = list1;
pLinkNode second = list2;
if((first == NULL)||(second == NULL))
{
return -1;
}
while(first->next)
{
first = first->next;
}
while(second->next)
{
second->next;
}
if(first == second)
{
return 1;
}
else
{
return -1;
}
}
//测试
//test.c
#include "LinkList.h"
void test()
{
pLinkList MyList;
pLinkNode rec = NULL;
int ret = 0;
InitLinkList(&MyList);
PushBack(&MyList,1);
PushBack(&MyList,2);
PushBack(&MyList,3);
PrintList(MyList);
PopBack(&MyList);
PrintList(MyList);
PushFront(&MyList, 4);
PrintList(MyList);
PopFront(&MyList);
PrintList(MyList);
ret = GetListLength(MyList);
printf("ret = %d\n",ret);
rec = Find(MyList, 2);
if(rec == NULL)
printf("表中没有此元素!!\n");
else
printf("rec = %d\n", rec->data);
Insert(&MyList, rec, 6);
PrintList(MyList);
Erase(&MyList, rec);
PrintList(MyList);
Remove(&MyList, 6);
PrintList(MyList);
Remove(&MyList, 1);
PrintList(MyList);
PushBack(&MyList,1);
PushBack(&MyList,2);
PushBack(&MyList,1);
PushBack(&MyList,3);
PushBack(&MyList,1);
PrintList(MyList);
RemoveAll(&MyList, 1);
PrintList(MyList);
Destroy(&MyList);
}
//BubbleSort()
void test2()
{
pLinkList MyList;
pLinkNode ret = NULL;
InitLinkList(&MyList);
PushBack(&MyList,1);
PushBack(&MyList,2);
PushBack(&MyList,3);
PrintList(MyList);
ret = Find(MyList, 2);
EraseNotTail(ret);
PrintList(MyList);
//PushBack(&MyList,3);
PushBack(&MyList,4);
PushBack(&MyList,5);
PrintList(MyList);
ReverseList(&MyList);
PrintList(MyList);
BubbleSort(&MyList);
PrintList(MyList);
Destroy(&MyList);
}
//InsertFrontNode()
void test3()
{
pLinkList MyList;
pLinkNode ret = NULL;
InitLinkList(&MyList);
PushBack(&MyList,1);
PushBack(&MyList,2);
PushBack(&MyList,3);
PrintList(MyList);
ret = Find(MyList, 2);
printf("ret->data = %d\n",ret->data);
InsertFrontNode(ret, 4);
PrintList(MyList);
Destroy(&MyList);
}
//Merge() , _Merge()
void test4()
{
pLinkList list1;
pLinkList list2;
pLinkNode NewList = NULL;
InitLinkList(&list1);
InitLinkList(&list2);
PushBack(&list1,1);
PushBack(&list1,3);
PushBack(&list1,4);
PrintList(list1);
PushBack(&list2,2);
PushBack(&list2,5);
PushBack(&list2,6);
PrintList(list2);
NewList = _Merge(list1,list2);
PrintList(NewList);
Destroy(&NewList);
}
//JosephCycle()
void test5()
{
pLinkList MyList;
pLinkNode ret = NULL;
int i = 0;
InitLinkList(&MyList);
for(i=1; i<=41; i++)
{
PushBack(&MyList, i);
}
//创建环
ret = Find(MyList, 41);
ret->next = MyList;
ret = JosephCycle(&MyList, 3);
printf("ret = %d\n", ret->data);
//结环,销毁空间
ret->next = NULL;
free(ret);
ret = NULL;
}
//FindMidNode()
void test6()
{
pLinkList MyList;
pLinkNode ret = NULL;
InitLinkList(&MyList);
PushBack(&MyList, 1);
PushBack(&MyList, 2);
PushBack(&MyList, 3);
PushBack(&MyList, 4);
PushBack(&MyList, 5);
PushBack(&MyList, 6);
PrintList(MyList);
ret = FindMidNode(MyList);
printf("ret = %d\n", ret->data);
Destroy(&MyList);
}
//DelKNode()
void test7()
{
pLinkList MyList;
pLinkNode ret = NULL;
InitLinkList(&MyList);
PushBack(&MyList, 1);
PushBack(&MyList, 2);
PushBack(&MyList, 3);
PushBack(&MyList, 4);
PushBack(&MyList, 5);
PushBack(&MyList, 6);
PrintList(MyList);
DelKNode(&MyList, 8);
PrintList(MyList);
Destroy(&MyList);
}
//CheckCycle() , GetCircleLength() ,GetCycleEntryNode()
void test8()
{
pLinkList MyList;
pLinkNode ret1 = NULL;
pLinkNode ret2 = NULL;
pLinkNode ret = NULL;
pLinkNode entry = NULL;
int i = 0;
InitLinkList(&MyList);
for(i=1; i<=7; i++)
{
PushBack(&MyList, i);
}
//创建环
ret1 = Find(MyList, 4);
ret2 = Find(MyList, 7);
ret2->next = ret1;
ret = CheckCycle(MyList);
if(ret == NULL) //不带环
{
printf("LinkList not cycle!!\n");
}
else //带环
{
printf("LinkList is cycle!!\n");
}
entry = GetCycleEntryNode(MyList, ret);
printf("EntyrNode = %d\n", entry->data);
printf("CircleLength = %d\n",GetCircleLength(ret));
ret2->next = NULL; //解环
Destroy(&MyList);
}
int main()
{
//test();
//test2();
//test3();
test4();
//test5();
//test6();
//test7();
//test8();
system("pause");
return 0;
}
本文出自 “Pzd流川枫” 博客,请务必保留此出处http://xujiafan.blog.51cto.com/10778767/1747968