您的位置:首页 > 编程语言 > C语言/C++

C语言实现单链表

2017-04-12 18:08 183 查看
#include<stdio.h>
#include<malloc.h>
#include<assert.h>

typedef int DataType;
typedef struct Node
{
DataType data;//数据域
struct Node* next;//保存下一个节点地址的指针域
}Node,*PNode;

void InitList(PNode* pHead)//初始化 传二级指针
{
assert(pHead);
*pHead = NULL;
}

PNode BuyNode(DataType data)//申请新节点
{
PNode pTemp = (PNode)malloc(sizeof(Node));//申请空间
if(pTemp)//空间申请成功,若不成功直接返回NULL
{
pTemp->data = data;
pTemp->next = NULL;
}
return pTemp;
}
void PushBack(PNode* pHead, DataType data)//尾插
{
assert(pHead);
if(*pHead == NULL)//空链表
{
*pHead = BuyNode(data);
}
else//链表不为空
{
PNode pcur = *pHead;
while(pcur->next)
{
pcur = pcur->next;
}
pcur->next = BuyNode(data);
}
}
void PopBack(PNode* pHead)//尾删
{
assert(pHead);
if(*pHead == NULL)//链表为空
{
return;
}
else if((*pHead)->next == NULL)//链表只有一个节点
{
free(*pHead);
*pHead = NULL;
}
else//链表有多个节点
{
PNode pcur = *pHead;
PNode pre = pcur;
while(pcur->next)
{
pre = pcur;
pcur = pcur->next;
}
free(pcur);
pre->next = NULL;
}
}
void PrintList(PNode pHead)//正序打印 不需二级指针,不改变外部实参
{
PNode pcur = pHead;
while(pcur)
{
printf("%d->",pcur->data);
pcur = pcur->next;
}
printf("NULL\n");
}
///////////////////////////////////面试题1//////单链表逆置打印 递归//////////////////////////////////////////
void PrintTail2Head(PNode pHead)
{
if(pHead)
{
PrintTail2Head(pHead->next);
printf("%d->",pHead->data);
}
}
void PushFront(PNode* pHead, DataType data)//头插
{
assert(pHead);
if(*pHead == NULL)//空链表与下面的非空情况可以合并到一起
{
*pHead = BuyNode(data);
}
else
{
PNode newnode = BuyNode(data);
if(newnode)//必须判断新节点是否创建成功,成功才可以插入
{
newnode->next = *pHead;//先将节点链接起来,否则可能丢失原链表
*pHead = newnode;//然后让第一个节点的指针再指向新节点
}
}
}
void PopFront(PNode* pHead)//头删
{
assert(pHead);
if(pHead == NULL)//分两种情况 链表为空
{
return;
}
//非空
else
{
PNode pTemp = *pHead;//先保存第一个节点
*pHead = (*pHead)->next;//再让第一个节点向后移动
free(pTemp);//释放掉第一个节点
pTemp = NULL;
}
}
PNode Find(PNode pHead, DataType data)//查找data元素的位置
{
PNode pTemp = pHead;
while(pTemp)
{
if(pTemp->data == data)
{
return pTemp;
}
pTemp = pTemp->next;
}
return NULL;//不存在返回空
}
void Insert(PNode pos, DataType data)//在pos位置后插入元素
{
PNode newnode = NULL;//为啥要先赋空???
if(pos == NULL)//插入位置是否合法
{
return;
}
newnode = BuyNode(data);//先申请新节点
newnode->next = pos->next;//让新节点的next指向pos的next
pos->next = newnode;//然后让pos的next指向新节点
}
void Erase(PNode* pHead, PNode pos)//要给出外部头指针。因为pos若为头结点 有可能改变头结点的值
{
assert(pHead);//链表是否存在
if(pHead == NULL || pos == NULL)//链表为空或位置不合法
{
return;
}

if(pos == *pHead)//删除位置为头结点
{
*pHead = pos->next;//头结点后移
free(pos);//删除头节点
}
else
{
PNode pcur = *pHead;
while(pcur->next != pos)
{
pcur = pcur->next;
}
pcur->next = pos->next;
free(pos);
}
}
/////////////////////////////////面试题2////////删除非尾节点,不能遍历链表 其实是删除pos的下一个节点//////////////////
void DelNotTail(PNode pos)
{
PNode Delnode =NULL;
if(NULL == pos || pos->next ==NULL)
return;
Delnode = pos->next;
pos->data = Delnode->data;
pos->next = Delnode->next;
free(Delnode);
}
/////////////////////////////////面试题3/////////////在非头结点前插入元素(头结点也可以) 在pos后插 然后交换值///////////////
void InsertNotHead(PNode pos, DataType data)
{
PNode newnode = NULL;//?????????
if(pos == NULL)
return;
newnode = BuyNode(pos->data);
if(newnode)//必须判断节点是否申请成功
{
newnode->next = pos->next;
pos->next = newnode;
pos->data = data;
}
}
void Remove(PNode pHead, DataType data)//删除值为data的元素,直接调用Erase函数(传引用)与Find函数(不传引用)
{
assert(pHead);
Erase(&pHead, Find(pHead, data));
}
void RemoveAll(PNode* pHead, DataType data)//删除所有值为data的元素!!!!!!!!!!!!!!!!!!!!!有问题
{
PNode pcur = NULL;
PNode pre = NULL;
assert(pHead);//链表是否存在

pre = *pHead;//定义两个指针 一个指向第一个节点
pcur = pre->next;//指向第二个节点

while(pcur)//遍历一遍单链表
{
if(pcur->data == data)//若pcur指向的节点值为data
{
pre->next = pcur->next;
free(pcur);//释放pcur
//pcur = pre;//让pcur指向前一个
pcur = pre->next;
}
else
{
pcur = pcur->next;
}

}

if((*pHead)->data == data)//如果头节点值为data的情况
{
pcur = *pHead;
*pHead = (*pHead)->next;
free(pcur);
}
}

size_t Size(PNode pHead)//链表中元素个数
{
PNode pcur = NULL;
int count = 0;

assert(pHead);
pcur = pHead;
while(pcur)
{
count++;
pcur = pcur->next;
}
return count;
}
//PNode Front(PNode pHead)
//{
//	assert(pHead);
//	return pHead;
//}
PNode Back(PNode pHead)
{
PNode pcur = pHead;
if(NULL == pHead)
return NULL;
while(pcur->next)
{
pcur = pcur->next;
}
return pcur;
}
//int Empty(PNode pHead);
//////////////////////////////////////面试题//////////约瑟夫环/////////////////////////////////////////////
PNode JosephCircle(PNode pHead, size_t M)
{
PNode pCur = pHead;
PNode pTemp = NULL;
if(pHead == NULL)
return NULL;
while(pCur->next != pCur)
{
size_t count = M;
while(--count)
{
pCur = pCur->next;
}
pTemp = pCur->next;
pCur->data = pTemp->data;
pCur->next = pTemp->next;
free(pTemp);
}
return pCur;
}
//////////////////////////////////////////////测试////////////////////////////////////////////
void FunTest4()
{
PNode pHead, pos;
int count = 0;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
PushBack(&pHead, 5);

//Erase(&pHead, Find(pHead, 3));
//Remove(pHead, 2);
//RemoveAll(&pHead, 2);///////////有问题啊
/////////////////////////////////////////////约瑟夫环//////////////////////////////////////
pos = Back(pHead);//构环
pos->next = pHead;//构环
pHead = JosephCircle(pHead, 3);
pHead->next = NULL;
PrintList(pHead);

//count = Size(pHead);
//printf("%d\n",count);
}

void FunTest()
{
PNode pHead;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
PrintList(pHead);
PushFront(&pHead, 5);
PrintList(pHead);
PrintTail2Head(pHead);

PopBack(&pHead);
PrintList(pHead);

PopBack(&pHead);
PopBack(&pHead);
PrintList(pHead);

PopBack(&pHead);
PrintList(pHead);

PopBack(&pHead);
PrintList(pHead);

}

void FunTest1()
{
PNode pHead;
InitList(&pHead);
PushFront(&pHead, 1);
PushFront(&pHead, 2);
PushFront(&pHead, 3);
PushFront(&pHead, 4);
PrintList(pHead);
PopFront(&pHead);
PrintList(pHead);
PrintTail2Head(pHead);
}

void FunTest2()
{
PNode pHead, pos;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
pos = Find(pHead, 2);
Insert(pos,5);
PrintList(pHead);
Erase(&pHead, Find(pHead, 5));
PrintList(pHead);

Erase(&pHead, Find(pHead, 1));
PrintList(pHead);

DelNotTail(Find(pHead, 2));///只能删除非尾节点
PrintList(pHead);
}

void FunTest3()
{
PNode pHead;
InitList(&pHead);
PushBack(&pHead, 1);
PushBack(&pHead, 2);
PushBack(&pHead, 3);
PushBack(&pHead, 4);
PrintList(pHead);
InsertNotHead(Find(pHead, 2),5);
PrintList(pHead);
}

int main()
{
FunTest4();
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 单链表