链表在C语言项目中很常见,学号链表,先从单链表开始,通常在学习阶段的单链表实现是基于某种数据类型或结构量身定做的操作方法,这种方法,没有通用性,在实际项目开发中,段不可取。于是乎,学习一种“浮云”般对单链表的操作是非常重要的。我们研究各个数据结点的数据,就会发现,无论它是什么类型,都有一个共同的特点,就是,他们都是存储在内存中的,它们拥有各子唯一的内存地址,于是乎,我们使用单链表的每个结点存储目标数据的地址,就可以抽象出一种通用的单链表操作方法,具体的操作方法,如下,此代码支持任何数据类型的单链表操作:
/**********************************************************************************************/
file : LinkList.h
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
typedef void LinkList;
typedef void LinkListNode;
extern LinkList* LinkList_Create();
extern void LinkList_Destroy(LinkList* list);
extern void LinkList_Clear(LinkList* list);
extern int LinkList_Length(LinkList* list);
extern int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
extern LinkListNode* LinkList_Get(LinkList* list, int pos);
extern LinkListNode* LinkList_Delete(LinkList* list, int pos);
extern void LinkList_Reverse(LinkList* list);
#endif
/*******************************************************************************************************/
file : LinkList.c
#include <stdio.h>
#include <malloc.h>
#include "LinkList.h"
typedef struct _tag_TLinkListNode TLinkListNode;
struct _tag_TLinkListNode
{
unsigned int addr;
TLinkListNode* next;
};
typedef struct _tag_TLinkList
{
int length;
TLinkListNode* header;
}TLinkList;
LinkList* LinkList_Create()
{
TLinkList* ret = (TLinkList*)malloc(sizeof(TLinkList));
if(ret != NULL)
{
ret->length = 0;
ret->header = NULL;
}
return (LinkList*)ret;
}
void LinkList_Destroy(LinkList* list)
{
LinkList_Clear(list);
free(list);
list = NULL;
}
void LinkList_Clear(LinkList* list)
{
TLinkList* sList = (TLinkList*)list;
if(sList != NULL)
{
while(sList->header != NULL)
{
TLinkListNode* pList = sList->header;
sList->header = pList->next;
free(pList);
sList->length--;
}
}
}
/************************************************************************
* 获取单链表长度
* 返回-1表示获取失败
* 返回非负数既是单链表当前长度
************************************************************************/
int LinkList_Length(LinkList* list)
{
int ret = -1;
TLinkList* sList = (TLinkList*)list;
if(sList != NULL)
{
ret = sList->length;
}
return ret;
}
/************************************************************************
* 插入结点
* 插入成功返回真
* 插入失败返回假
************************************************************************/
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
{
int i = 0;
TLinkList* sList = (TLinkList*)list;
int ret = (sList != NULL) && (pos >= 0) && (node != NULL);
if(ret)
{
TLinkListNode* pNew = (TLinkListNode*)malloc(sizeof(TLinkListNode));
if(pNew != NULL)
{
pNew->addr = (unsigned int)node;
if(pos == 0 || sList->header == NULL)
{
pNew->next = sList->header;
sList->header = pNew;
}
else
{
TLinkListNode* current = sList->header;
for(i = 1; (i < pos) && (current->next != NULL); i++)
{
current = current->next;
}
pNew->next = current->next;
current->next = pNew;
}
sList->length++;
}
else
{
ret = 0;
}
}
return ret;
}
/************************************************************************
* 获取pos位置的结点
* 成功返回结点指针
* 失败返回空
************************************************************************/
LinkListNode* LinkList_Get(LinkList* list, int pos)
{
int i = 0;
TLinkList* sList = (TLinkList*)list;
LinkListNode* ret = NULL;
if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
{
if(0 == pos)
{
ret = (LinkListNode*)(sList->header->addr);
}
else
{
TLinkListNode* current = sList->header;
for(i=1; i<pos; i++)
{
current = current->next;
}
ret = (LinkListNode*)(current->next->addr);
}
}
return ret;
}
/************************************************************************
* 删除pos位置的结点,并将删除的结点指针返回
* 成功返回结点指针
* 失败返回空
************************************************************************/
LinkListNode* LinkList_Delete(LinkList* list, int pos)
{
TLinkList* sList = (TLinkList*)list;
LinkListNode* ret = NULL;
int i = 0;
if( (sList != NULL) && (0 <= pos) && (pos < sList->length) )
{
TLinkListNode* current = sList->header;
if(0 == pos)
{
ret = (LinkListNode*)(sList->header->addr);
sList->header = current->next;
free(current);
}
else
{
for(i=0; i<pos-1; i++)
{
current = current->next;
}
ret = (LinkListNode*)(current->next->addr);
current->next = current->next->next;
free(current->next);
}
sList->length--;
}
return ret;
}
/************************************************************************
* 两种单链表逆序的操作
* 无返回值
************************************************************************/
#if 1
/************************************************************************
// 修改结点指针
void LinkList_Reverse(LinkList* list)
{
TLinkList* sList = (TLinkList*)list;
TLinkListNode* p1 = sList->header;
if(LinkList_Length(list) == 2)
{
sList->header = p1->next;
sList->header->next = p1;
p1->next = NULL;
}
else if(LinkList_Length(list) > 2)
{
TLinkListNode* p2 = p1->next;
sList->header = p2->next;
p1->next = NULL;
while(sList->header != NULL)
{
p2->next = p1;
p1 = p2;
p2 = sList->header;
sList->header = sList->header->next;
}
sList->header = p2;
p2->next = p1;
}
}
#else
// 利用单链表删除、插入操作,将原有单链表第0个数据结点取出来,存入临时单链表中的第0个数据
// 结点位置,直到原有单链表为空,再将临时单链表还给原有链表指针
void LinkList_Reverse(LinkList* list)
{
if(LinkList_Length(list) >= 2)
{
TLinkList* sList = (TLinkList*)list;
LinkList* swapList = LinkList_Create();
while(sList->header != NULL)
{
LinkList_Insert(swapList, LinkList_Delete(list, 0), 0);
}
sList->header = ((TLinkList*)swapList)->header;
sList->length = ((TLinkList*)swapList)->length;
((TLinkList*)swapList)->header = NULL;
((TLinkList*)swapList)->length = 0;
LinkList_Destroy(swapList);
}
}
#endif