单链表非常经典,还是面试中常考的内容。
相对于有序表,有不同的地方,可以通过修改之前的有序表来编写单链表。
有以下特征:
1.有数据域和有指针域
2.插入和删除比较方便
3.长度没有限制
4.查找不方便
5.结点的存储地址可以不连续
1 #ifndef _STRUCTLINKLIST_H_
2 #define _STRUCTLINKLIST_H_
3 enum{
4 ERROR = -1,
5 OK,
6 FALSE = 0,
7 TRUE
8 };
9 typedef int Status;
10 typedef int ElemType;
11 typedef struct LNode{
12 ElemType data;
13 struct LNode * next;
14 }LinkList, * pLinkList;
15
16 #endif
Elemtype是为了可移植性, *pLinkList是为了方便以后定义指针,之后定义指针都是直接pLinkList 。。。这样写的
#include<stdio.h>
#include"StructLinkList.h"
#include<stdlib.h>
/*point at Head Node*/
pLinkList InitHeadNode()
{
pLinkList pHead;
pHead = (pLinkList)malloc(sizeof(LinkList));
pHead->next = NULL;
return pHead;
}
初始化头结点。
/*************************************************************************
> File Name: Show.c
> Author: aaron
> Mail: 60360329@163.com
> Created Time: Wed 15 Mar 2017 03:35:21 PM CST
************************************************************************/
#include<stdio.h>
#include"StructLinkList.h"
void show(pLinkList pLink)
{
pLinkList pTmp = pLink->next;
if (NULL == pLink|| NULL == pTmp)
return;
int i;
for(i = 0 ; i < 10 ;i++)
printf("%d\t",i+1);
printf("\n");
while(pTmp)
{
printf("%d\t",pTmp->data);
pTmp = pTmp->next;
}
printf("\n");
}
显示链表中的内容,定义的元素类型是整形,打印数字。通过创建指针,移动遍历整个链表,到null时停止。
/*************************************************************************
> File Name: IsEmpty.c
> Author: aaron
> Mail: 60360329@163.com
> Created Time: Wed 15 Mar 2017 11:10:01 AM CST
************************************************************************/
#include<stdio.h>
#include"StructLinkList.h"
Status IsEmpty(pLinkList pLink)
{
if(pLink->next)
return TRUE;
else
return FALSE;
}
判断空
/*************************************************************************
> File Name: Insert_BY_Head.c
> Author: aaron
> Mail: 60360329@163.com
> Created Time: Wed 15 Mar 2017 01:37:11 PM CST
************************************************************************/
#include<stdio.h>
#include"StructLinkList.h"
#include<stdlib.h>
Status InsertByHead(pLinkList pHead,ElemType INdata)
{
pLinkList pTmp = (pLinkList)malloc(sizeof(LinkList));
pTmp->data = INdata;
pTmp->next = pHead->next;
pHead->next = pTmp;
return OK;
}
头插法。新节点保存头结点指向后的指针,再由头结点指向新结点。
/*************************************************************************
> File Name: Delete_by_Head.c
> Author: aaron
> Mail: 60360329@163.com
> Created Time: Wed 15 Mar 2017 02:42:26 PM CST
************************************************************************/
#include<stdio.h>
#include"StructLinkList.h"
#include<stdlib.h>
ElemType DeleteByHead(pLinkList pLink)
{
pLinkList pTmp = pLink->next;
ElemType OUTdata = pTmp->data;
pLink->next = pTmp->next;
free(pTmp);
return OUTdata;
}
不要忘了free。
1 #include<stdio.h>
2 #include"StructLinkList.h"
3
4 int LenghtOfLinkList(pLinkList pLink)
5 {
6 int count = 0;
7 pLinkList pTmp = pLink->next;
8 while(pTmp)
9 {
10 count++;
11 pTmp = pTmp->next;
12 }
13 return count;
14 }
求长度也是遍历链表
/*************************************************************************
> File Name: DestroyLinkList.c
> Author: aaron
> Mail: 60360329@163.com
> Created Time: Wed 15 Mar 2017 10:13:30 AM CST
************************************************************************/
#include<stdio.h>
#include"StructLinkList.h"
#include<stdlib.h>
Status DestroyLinkList(pLinkList pLink)
{
if (NULL == pLink)
return ERROR;
pLinkList pTmp;
while(pLink)
{
pTmp = pLink->next;
free(pLink);
pLink = pTmp;
}
return OK;
}
Status CleanLinkList(pLinkList pLink)
{
pLinkList pTmp1,pTmp2;
pTmp1 = pLink->next;
while(pTmp1)
{
pTmp2 = pTmp1->next;
free(pTmp1);
pTmp1 = pTmp2;
}
//DestroyLinkList(pLink->next); the another way
return OK;
}
销毁和清除函数。差不多一样写在一起了
/*************************************************************************
> File Name: SreachItem.c
> Author: aaron
> Mail: 60360329@163.com
> Created Time: Wed 15 Mar 2017 02:58:34 PM CST
************************************************************************/
#include<stdio.h>
#include"StructLinkList.h"
pLinkList SreachItem(pLinkList pLink,ElemType INdata)
{
pLinkList pTmp = pLink;
while(INdata != pTmp->data)
{
pTmp = pTmp->next;
if (NULL == pTmp)
{
printf("there is not the data!\n");
return NULL;
}
}
return pTmp;
}
查找,同样也是遍历不过要知道找不到怎么处理。
1 /*************************************************************************
2 > File Name: UpdateItem.c
3 > Author: aaron
4 > Mail: 60360329@163.com
5 > Created Time: Wed 15 Mar 2017 03:07:03 PM CST
6 ************************************************************************/
7
8 #include<stdio.h>
9 #include"StructLinkList.h"
10
11 void UpdateItem(pLinkList pLink,int location,ElemType INdata)
12 {
13 if (NULL == pLink)
14 return;
15 if (location < 0)
16 {
17 printf("location is so small\n");
18 return;
19 }
20 pLinkList pTmp = pLink;
21 while(location--)
22 {
23 if(NULL == pTmp->next->next)
24 {
25 printf("location is so big\n");
26 return;
27 }
28 pTmp = pTmp->next;
29 }
30 pTmp->data = INdata;
31 }
这个是更新内容原理和查找差不多。
/*************************************************************************
> File Name: DelItem.c
> Author: aaron
> Mail: 60360329@163.com
> Created Time: Wed 15 Mar 2017 09:39:27 PM CST
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include"StructLinkList.h"
Status DelItem(pLinkList pLink,int location,ElemType * OUTdata)
{
if (NULL == pLink)
{
exit(-1);
}
pLinkList pTmp = pLink;
pLinkList qTmp = pLink->next;
while(--location)
{
pTmp = pTmp->next;
if (NULL == pTmp)
{
printf("the number is big!\n");
return ERROR;
}
qTmp = qTmp->next;
}
if (NULL == qTmp)
{
printf("the number is big!\n");
return ERROR;
}
pTmp->next = qTmp->next;
*OUTdata = qTmp->data;
free(qTmp);
}
删除要防止越界。
用两个指针记录录要删除位置之前的节点还有当前删除结点。
删除是要ptmp的next指针指向下下个结点。
释放qtmp
1 /*************************************************************************
2 > File Name: InsertItemForLink.c
3 > Author: aaron
4 > Mail: 60360329@163.com
5 > Created Time: Wed 15 Mar 2017 11:43:05 AM CST
6 ************************************************************************/
7
8 #include<stdio.h>
9 #include<stdlib.h>
10 #include"StructLinkList.h"
11
12 void InsertItemForLink(pLinkList pLink,int location,ElemType INdata)
13 {
14 if (NULL == pLink)
15 return;
16 pLinkList pTmp = (pLinkList)malloc(sizeof(LinkList));
17 pTmp->data = INdata;
18 pLinkList qTmp = pLink;
19 while(--location)
20 qTmp = qTmp->next;
21 pTmp->next = qTmp->next;
22 qTmp->next = pTmp;
23 }
这里没有下防止越界的语句但是和上面的类似。
1 /*************************************************************************
2 > File Name: reversLinkList.c
3 > Author: aaron
4 > Mail: 60360329@163.com
5 > Created Time: Wed 15 Mar 2017 10:26:12 PM CST
6 ************************************************************************/
7
8 #include<stdio.h>
9 #include<stdlib.h>
10 #include"StructLinkList.h"
11 pLinkList reversLinkList(pLinkList pLink)
12 {
13 if (NULL == pLink)
14 exit(ERROR);
15 pLinkList rem = pLink;
16 pLink = pLink->next;
17 pLinkList NextTmp = NULL;
18 pLinkList PreTmp = NULL;
19 while(NULL != pLink)
20 {
21 NextTmp = pLink->next;
22 pLink->next = PreTmp;
23 PreTmp = pLink;
24 pLink = NextTmp;
25 }
26 rem->next = PreTmp;
27 printf("\n");
28 return rem;
29 }
倒置链表,这个是除开头结点的倒置,记录下处理之前的位置pretmp,还有之后要处理的next
单链表操作要保存next为先,这里也一样,然后为了倒置,把当前链表的next指针指向pre(之前遍历到的结点)那么,我们就实现了把指针反向。
把当前结点存在pre,向后移动结点。当然plink是实实在的地址,是把地址在不停的赋值,作用在抽象的链表上,不像之前定义的ptmp是不会改变链表的
所以改变链表就要动plink。最后把之前保存好的头结点指向pre。因为循环结束条件是plink为null,那么pre里就存放了已经倒置了链表。
————————若有错误请大神指出,谢谢!!