链式存储结构:
定义:为了标识每个数据元素于其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还要存储指示其直接后继的信息。
单链表:每个节点中只包含一个指针域
头节点:链表中的第一个节点。他包含了指向第一个数据元素的指针以及额外的信息;
数据节点:链表中代表数据元素的节点,包含指向下一个节点的指针和数据元素。
尾节点:链表中的最后一个节点,其下一个元素指针为空
实例如下:
//linklist.h文件
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
typedef struct linklistnode
{
struct linklistnode *next;
int item;
}LinkListNode; //数据节点
typedef struct linklist
{
LinkListNode header;
int length;
}LinkList; //头节点
LinkList *LinkList_Create();
void LinkList_Destroy(LinkList *list);
void LinkList_Clear(LinkList *list);
int LinkList_Length(LinkList *list);
int LinkList_Insert(LinkList *list, LinkListNode *node, int pos);
LinkListNode *LinkList_Get(LinkList *list,int pos);
LinkListNode *LinkList_Delete(LinkList *list,int pos);
#endif //__LINKLIST_H__
//linklist.c文件
#include <stdlib.h>
#include "linklist.h"
//创建
LinkList *LinkList_Create()
{
LinkList *ret = NULL;
ret = malloc(sizeof(LinkList));
if(ret!=NULL)
{
ret->length = 0;
ret->header.next = NULL;
}
return ret;
}
//销毁
void LinkList_Destroy(LinkList *list)
{
free(list);
}
//清空
void LinkList_Clear(LinkList *list)
{
if(list!=NULL)
{
list->length =0;
list->header.next = NULL;
}
}
//求长度
int LinkList_Length(LinkList *list)
{
int ret = -1;
if( list!=NULL )
{
ret = list->length;
}
return ret;
}
//插入
int LinkList_Insert(LinkList *list, LinkListNode *node, int pos)
{
int ret = list!=NULL && node!=NULL && pos>=0;
if( ret )
{
int i;
LinkListNode *cur = (LinkListNode *)list;
for(i=0;i<pos && cur->next!=NULL;i++)
{
cur = cur->next;
}
node->next = cur->next; //这里插入的顺序不要写反。
cur->next = node;
list->length++;
}
return ret;
}
//获得
LinkListNode *LinkList_Get(LinkList *list,int pos)
{
LinkListNode *ret = NULL;
if( list!=NULL && (0<=pos && pos<list->length) )
{
int i;
LinkListNode *cur = (LinkListNode *)list;
for(i=0; i<pos; i++)
cur = cur->next;
ret = cur->next; //因为从0开始计数的,要第三个数,那么就是第二个数的next
}
return ret;
}
//删除
LinkListNode *LinkList_Delete(LinkList *list,int pos)
{
LinkListNode *ret = NULL;
if(list!=NULL && (0<=pos&&pos<list->length) )
{
int i;
LinkListNode *cur = (LinkListNode *)list;
for(i=0; i<pos; i++)
cur = cur->next;
ret = cur->next; //单向链表是从0开始排的。
cur->next = ret->next;
list->length--;
}
return ret;
}
//main.c文件
#include <stdio.h>
#include "linklist.h"
int main( void )
{
int i;
LinkListNode *p = NULL;
LinkListNode v1 = {NULL,1};
LinkListNode v2 = {NULL,2};
LinkListNode v3 = {NULL,3};
LinkListNode v4 = {NULL,4};
LinkList *list = LinkList_Create(); //创建后返回创建好的头节点ret(指向头节点的指针)
LinkList_Insert(list,&v1,0); //都是头插入
LinkList_Insert(list,&v2,0);
LinkList_Insert(list,&v3,0);
LinkList_Insert(list,&v4,0);
for(i=0; i<LinkList_Length(list);i++)
{
p = LinkList_Get(list,i);
printf("%d ",p->item);
}
printf("\n");
LinkList_Destroy(list);
}
//Makefile
cc :=gcc
main : main.o linklist.o
gcc $^ -o $@
.PHONY : main clean
clean:
rm -rf *.o main
我的感悟:
上面的这个代码自我感觉比较好用,以后的很多例子都是在这个单向链表的基础上实现的,所以,自我感觉应该要把这个代码敲的和hello world一样熟悉。