单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
在实际生产中,有可能在软件启动后,对一些数据进行多态扩容,比如,网卡收发包的时候,从协议栈上产生一个需求的包,需要暂时排队,等网卡把数据发送出去后,在在队列里处理,所以这种利用堆中分散的内存,以结点为单位的数据结果是有一定的意义的。
- C语言实现,聊作记录
链表的数据的数据结构typedef struct node { int data; //数据域 struct node *next; //指针域 }NODE_t;
链表的创建
NODE_t *CreatNodeList() { NODE_t *head = NULL; head = (NODE_t *)malloc(sizeof(NODE_t)); if(!head) exit(-1); head->next = NULL; return head; }
链表的插入,头插入,有个头节点,方便遍历,处理
int InsertNode(NODE_t *head,int data)
{
NODE_t *cur = NULL;
if(!head)
exit(-1);
cur = (NODE_t *)malloc(sizeof(NODE_t));
if(!cur)
exit(-1);
cur->data = data;
//cur 插入到 head 和 head->next 之间
cur->next = head->next;
head->next = cur;
return 0;
}
结点的查找
NODE_t *findNode(NODE_t *head,int data)
{
head = head->next;
while(head)
{
if(head->data == data)
{
break;
}
head = head->next;
}
if(head == NULL)
{
printf("sorry,%d is not in the list\n",data);
}
return head;
}
结点的删除
int DeleteNodeOfList(NODE_t *head,NODE_t *pfind)
{
// 首先找到这个需要删除指针的前一个节点的指针
// 因为pfind 的合法性在外面判断,此处不再判断
while(head->next != pfind)
{
head = head->next;
}
head->next = pfind->next;
free(pfind);
pfind = NULL;
return 0;
}
这里的删除,假设结点数目很多,则会造成一个问题,单链表只能一个方向,则需要找到需要删除的节点的前驱指针,则需要从头开始遍历,比较浪费资源,所以,这个地方存在优化空间,就是,一旦拥有需要删除的节点,则可以这么操作
- 将需要删除节点后驱结点的数据域数据拷贝至当前的删除节点数据域
- 删除删除节点的后驱指针
优化版本如下:
// 优化点: 不必每次都遍历所有的节点,找到前驱节点
// 将这个需要删除的节点的后驱节点的数据域拷贝过来,然后删除这个后驱节点
int DeleteNodeOfList_Better(NODE_t *head,NODE_t *pfind)
{
NODE_t *p = pfind->next;
//最后一个节点,它其后没有后驱节点,所以需要从头遍历,找到它的前置节点
if(pfind->next == NULL)
{
while(head->next != pfind)
{
head = head->next;
}
head->next = pfind->next;
free(pfind);
pfind = NULL;
}
else //对于除最后一个节点的外的其他位置节点,则使用覆盖后删除后置节点的方式实现删除
{
pfind->data = pfind->next->data;
pfind->next = pfind->next->next;
free(p);
p = NULL;
}
return 0;
}
一旦找到结点的指针操作只是针对数据域的一个操作,比较便捷
结点的修改
int UpdateNode(NODE_t *head,int olddata,int newdata)
{
NODE_t *p = findNode(head,olddata);
if(p)
{
p->data = newdata;
}
return 0;
}
遍历打印显示
void showList(NODE_t *head)
{
head = head->next;
while(head)
{
printf("%d ==> ",head->data);
head = head->next;
}
printf("end..\n");
}
链表的排序
int sortList(NODE_t *head)
{
int i = 0,j = 0;
int listlen = 0;
int tmpData = 0;
NODE_t *p = NULL;
// 使用冒泡排序,不动指针域,比较数据域,使用临时变量,将有大小之别的节点的数据域交换
// 得到链表长度,方便冒泡
listlen = ListNodeLen(head);
// 指到首节点
p = head->next;
for(i = 0;i < listlen-1;i++)
{
// 每一轮从头开始
p = head->next;
for(j = 0;j<listlen - i-1;j++)
{
// 将小值排在前面
if(p->data > p->next->data)
{
tmpData = p->data;
p->data = p->next->data;
p->next->data = tmpData;
}
p = p->next;
}
}
return 0;
}
原文地址:http://blog.51cto.com/6306331/2073431
时间: 2024-10-29 03:33:19