一、链表节点类型
/*链表存储的数据的数据类型*/
typedef int DataType;
/*链表的结点类型*/
typedef struct node
{
DataType data; //数据域
struct node *pnext; //指针域:指向下一个结点
}Link_Node_t;
/*链表的对象类型*/
typedef struct link
{
Link_Node_t *phead; //链表头结点地址
int clen; //链表当前结点个数
}Link_t;
二、单向链表的基本操作
1.创建
Link_t *create_link()
{
Link_t *plink = malloc(sizeof(Link_t));
if (NULL == plink)
{
perror("fail malloc");
return NULL;
}
plink->phead = NULL;
plink->clen = 0;
return plink;
}
2.头插
int push_link_head(Link_t *plink, DataType data)
{
Link_Node_t *pnode = malloc(sizeof(Link_Node_t));
if (NULL == pnode)
{
perror("fail malloc");
return -1;
}
pnode->data = data;
pnode->pnext = NULL;
pnode->pnext = plink->phead;
plink->phead = pnode;
plink->clen++;
return 0;
}
3.遍历
void link_for_each(Link_t *plink)
{
Link_Node_t *p = plink->phead;
while (p != NULL)
{
printf("%d ", p->data);
p = p->pnext;
}
printf("\n");
}
4.判空
int is_empty_link(Link_t *plink)
{
return NULL == plink->phead;
}
5.尾插
int push_link_tail(Link_t *plink, DataType data)
{
Link_Node_t *pnode = malloc(sizeof(Link_Node_t));
if (NULL == pnode)
{
perror("fail malloc");
return -1;
}
pnode->data = data;
pnode->pnext = NULL;
if (is_empty_link(plink))
{
plink->phead = pnode;
}
else
{
Link_Node_t *p = plink->phead;
while (p->pnext != NULL)
{
p = p->pnext;
}
p->pnext = pnode;
}
plink->clen++;
return 0;
}
6.头删
int pop_link_head(Link_t *plink)
{
if (is_empty_link(plink))
{
return 0;
}
Link_Node_t *pdel = plink->phead;
plink->phead = pdel->pnext;
free(pdel);
plink->clen--;
return 1;
}
7.尾删
int pop_link_tail(Link_t *plink)
{
if (is_empty_link(plink))
{
return 0;
}
else if (1 == plink->clen)
{
pop_link_head(plink);
}
else
{
Link_Node_t *p = plink->phead;
while (p->pnext->pnext != NULL)
{
p = p->pnext;
}
free(p->pnext);
p->pnext = NULL;
plink->clen--;
}
return 1;
}
8.查找
Link_Node_t *find_link(Link_t *plink, int key)
{
if (is_empty_link(plink))
return NULL;
Link_Node_t *p = plink->phead;
while (p != NULL)
{
if (p->data == key)
{
return p;
}
p = p->pnext;
}
return NULL;
}
9.修改
int change_link(Link_t *plink, int key, DataType newdata)
{
Link_Node_t *pnode = find_link(plink, key);
if (pnode != NULL)
{
pnode->data = newdata;
return 0;
}
return -1;
}
10.销毁
void destroy_link(Link_t *plink)
{
while (!is_empty_link(plink))
{
pop_link_head(plink);
}
free(plink);
}
11.倒置
void reverse_link(Link_t *plink)
{
if (is_empty_link(plink))
return;
Link_Node_t *pinsert = NULL;
Link_Node_t *ptmp = plink->phead;
plink->phead = NULL;
while (ptmp != NULL)
{
pinsert = ptmp;
ptmp = ptmp->pnext;
pinsert->pnext = plink->phead;
plink->phead = pinsert;
}
}
12.排序(插入法)
void insert_sort_link(Link_t *plink)
{
if (is_empty_link(plink) || 1 == plink->clen)
{
return;
}
Link_Node_t *p = NULL;
Link_Node_t *pinsert = NULL;
Link_Node_t *ptmp = plink->phead->pnext;
plink->phead->pnext = NULL;
while (ptmp != NULL)
{
pinsert = ptmp;
ptmp = ptmp->pnext;
if (pinsert->data <= plink->phead->data)
{
pinsert->pnext = plink->phead;
plink->phead = pinsert;
}
else
{
p = plink->phead;
while (p->pnext != NULL && p->pnext->data < pinsert->data)
{
p = p->pnext;
}
pinsert->pnext = p->pnext;
p->pnext = pinsert;
}
}
}
练习1. 查找链表中间节点(返回中间节点的地址)
Link_Node_t *find_mid_node(Link_t *plink)
{
if (is_empty_link(plink))
return NULL;
Link_Node_t *pfast = plink->phead;
Link_Node_t *pslow = pfast;
while (pfast != NULL)
{
pfast = pfast->pnext;
if (NULL == pfast)
{
return pslow;
}
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return pslow;
}
练习2. 查找链表倒数第K个节点
Link_Node_t *find_last_k_node(Link_t *plink, int k)
{
if (is_empty_link(plink))
return NULL;
Link_Node_t *pfast = plink->phead;
Link_Node_t *pslow = pfast;
for (int i = 0; i < k; i++)
{
if (NULL == pfast)
{
return NULL;
}
pfast = pfast->pnext;
}
while (pfast != NULL)
{
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return pslow;
}
练习3. 删除指定节点
int pop_point_node(Link_t *plink,int key)
{
if (is_empty_link(plink))
return 0;
Link_Node_t *pdel = plink->phead;
Link_Node_t *ppre = NULL;
while (pdel != NULL)
{
if (pdel->data == key)
{
if (plink->phead == pdel)
{
pop_link_head(plink);
}
else
{
ppre->pnext = pdel->pnext;
free(pdel);
plink->clen--;
}
return 1;
}
else
{
ppre = pdel;
pdel = pdel->pnext;
}
}
return 0;
}