前言
一直以来对链表都理解的不深,没有个系统的总结学习。今天趁有空,总结一下,方便日后查阅。
一、链表
链表是C语言中的一种数据结构,链表由一系列结点(链表中每一个元素称为结点)组成,每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。由此可见,链表不像malloc的一块内存一样是连续顺序存储的,每个节点靠一个指针连接,指针指向的就是下个节点的地址。这就和数组有不同了,数组是在内存中是连续存储的,每个位置下标存入的是固定的值,所以查找很方便,但是如果要求快速插入和删除,数组就显得很局促了。但是链表就可以很快速的插入和删除,因为链表的数据是靠地址链接,我们只需要改变地址指向就可以了。
二、使用链表及链表的基本操作
链表定义
typedef struct Node
{
int data;
struct Node *next;
}NODE,pNODE;
可以看出,一个链表节点是由一个数据域和一个指针域组成。指针域的类型是一个完整的链表结构。注意此处用法,在链表内部定义链表节点的时候,要使用Node,而不是NODE,原因是typedef的用法。在typedef还没执行完的时候,NODE是未定义的,所以会出现未定义错误。
链表的基本操作为创建、查找、增加和删除。
下面贴个代码。
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *pNext;
}NODE,*pNODE;
pNODE CreateList(void)
{
int i, length, data;
pNODE p_new = NULL, pTail = NULL;
pNODE pHead = (pNODE)malloc(sizeof(NODE));//见注1
if (NULL == pHead)
{
printf("内存分配失败!\n");
exit(EXIT_FAILURE);
}
pHead->data = 0;
pHead->pNext = NULL;
pTail = pHead;//见注2
printf("请输入要创建链表的长度:\n");
scanf("%d", &length);
for (i=1; i<length+1; i++)
{
p_new = (pNODE)malloc(sizeof(NODE));
if (NULL == p_new)
{
printf("内存分配失败!\n");
exit(EXIT_FAILURE);
}
printf("请输入第%d个节点的值:\n", i);
scanf("%d", &data);
p_new->data = data;
p_new->pNext = NULL;
pTail->pNext = p_new;
pTail = p_new;
}
return pHead;
}
void PrintList(pNODE pHead)
{
pNODE pt = pHead->pNext;
printf("打印链表:\n");
while (pt != NULL)
{
printf("%d ", pt->data);
pt = pt->pNext;
}
putchar('\n');
}
int IsEmpty(pNODE pHead)
{
if (pHead->pNext == NULL)
return 1;
else
return 0;
}
int GetListLength(pNODE pHead)
{
int length = 0;
pNODE p = pHead->pNext;
while(p != NULL)
{
length++;
p = p->pNext;
}
return length;
}
void insertMylist(pNODE pHead,int addr,int data)
{
pNODE pt = (pNODE)malloc(sizeof(NODE));
pt->data = data;
while(1)
{
if(pHead->data == addr)
{
pt->pNext = pHead->pNext;
pHead->pNext = pt;
break;
}
pHead=pHead->pNext;
}
}
void deleteMylist(pNODE pHead,int addr)
{
pNODE pt;
while(1)
{
if(addr == pHead->data)
{
pHead = pHead->pNext;
break;
}
pt = pHead;//见注3
pHead = pHead->pNext;
}
free(pt->pNext);//见注4
pt->pNext = NULL;
pt->pNext = pHead;
}
int main ()
{
pNODE Mylist = CreateList();
PrintList(Mylist);
printf("length is %d \n",GetListLength(Mylist));
insertMylist(Mylist,3,100);
PrintList(Mylist);
printf("delete %d \n",3);
deleteMylist(Mylist,3);
PrintList(Mylist);
return(0);
}
几点解释,大佬绕行。
注1:创建头节点,头结点是第0个节点,后面的节点从1开始计数。
注2:头结点地址给尾结点,创建链表操作都在尾结点进行插入,保证头结点不变。
注3:记录查询到的上次节点位置。
注4:删除节点要进行free操作,否则会有内存泄漏。