线性表链式存储结构定义
该链表的每个结点是一个结构体,结构体内部有两个成员,一个成员是整形变量,称作数据域。另一个成员是结构体指针变量,存放下一个节点的首地址。
下面要引出一些概念:
头结点:顾名思义,头结点是整个单链表的最前面的结点,它有点儿特殊,它的数据域不用来存储数据,而是存储链表长度之类的属性信息,然后呢,它的指针域存储则是第一个数据结点的地址。
头指针:就是上面说的,头结点的指针域。
typedef struct Node
{
ElemType data;
struct Node *next;
};
typedef struct Node *LinkList;
看到这个代码我是晕的,我居然看不懂。但是,我最终查找资料还是看懂得了!!!
struct Node *next;
这句还算简单,就是定义了一个Node类型的结构体指针;
typedef struct Node *LinkList;
这句就厉害了,它的意思是把struct Node * 取了个别称为LinkList。这样用LinkList定义其它的变量其实就是定义了一个Node类型的结构体指针。原谅我太垃圾了,这也看不懂。
单链表的操作
定义了链表之后,我们也要规定好后续对链表的操作,这样才是抽象数据结构类型嘛。
单链表的读取
要读取第 loca 个数据的算法思路。
1 声明一个结点 p 指向链表的第一个结点,单链表的头结点存着第一个结点的地址,把这个地址给结构体指针,初始化 count从1开始。
2 当 count<loca 时,就遍历链表,让p的指针向后移动,不断指向下一结点,count每次累加1;
3 若到链表末尾p为空,则说明第loca个元素不存在;
4 否则查找成功,返回结点p的数据。
Status SingleListRead(LinkList single_list, int loca, ElemType *read_value)
{
LinkList p;
int count = 1;
p = single_list->next;
while(p && (count < loca))
{
p = p -> next;
count++;
}
if((!p) || (count > loca))
return ERROR;
*read_value = p -> data;
return OK;
}
单链表的插入
在loca位置插入数据:
1 声明一结点p指向单链表第一个结点,并且初始化计数器count = 1;
2 当count < loca时,遍历链表,让p的指针后移,不断指向下一个结点,count每次加1.
3 若到链表末尾p为空,则说明第i个元素不存在;
4 否则查找成功,在系统中生成一个空结点s
5 将数据元素e赋值给s->data
6 单链表的插入标准语句:插入结点先存后面结点的地址,再把插入结点的地址给前一结点。
7 返回OK。
这里需要注意,如果是在第loca个位置前插入新的结点,则第一个形参为:
Status SingleListInsert(LinkList *single_list, int loca, ElemType new_data)
如果是在第loca个位置后面插入新的结点,则函数的形参结构为:
Status SingleListInsert(LinkList single_list, int loca, ElemType new_data)
少了个*号。我是这样理解的:
有星号的时候,single_list为指针的指针,使用取地址符+single_list,就是代表遍历是从头结点开始的。
没有星号的时候,遍历是从第一个结点开始的。
本函数选择从第loca个结点的前面插入新的结点,故采用带星号的方式。
Status SingleListInsert(LinkList *single_list, int loca, ElemType new_data)
{
LinkList p,s;
int count = 1;
p = *single_list;
while(p && count < loca)
{
p = p->next;
count++;
}
if(!p || count > loca)
return ERROR;
s = (LinkList)malloc(sizeof(Node));
s->data = new_data;
s->next = p->next;
p->next = s;
return OK
}
单链表的删除
删除单链表第loca个结点算法思路:
1 声明一结点p指向链表第一个结点,初始化count = 1;
2 当count < loca 时,遍历单链表,p不断指向下一个结点,每次count加一;
3 若到链表末尾p为空,则说明该结点不存在,同时也要判断输入的loca是否小于1,是否合法。
4 否则查找成功,将需要删除的结点的地址p->next赋给q,再把q->next赋给p->next.
5 返回删除的值,释放q指针指向地址的空间,声明该空间可用。
6 返回 OK。
Status SingleListDelete(LinkList *single_list, int loca, ElemType *delete_data)
{
int count = 1;
LinkList p, q;
p = *single_list;
while(p && count < loca)
{
p = p->next;
count++;
}
if(!p || count > loca)
return ERROR;
q = p ->next;
*delete_data = q ->data;
p ->next = q ->next;
free(q);
return OK;
}
单链表的创建
单链表整表创建的算法思路:
1 声明一结点p和计数器count;
2 初始化一空链表L;
3 让L的头结点的指针指向NULL,即创建一个带头结点的单链表;
4 循环:
生成一新结点赋值给p
随机生成一数字赋值给p的数据域p->data;
将p插入到头结点与前一新结点之间
Status SingleListCreate(LinkList *single_list,int n)
{
LinkList p;
int count;
*single_list = (LinkList)malloc(sizeof(SL));
(*single_list)->data = NULL;
srand(time(0));
for(count =0; count < n; count++)
{
p = (LinkList)malloc(sizeof(SL));
p ->data = rand() % 100 + 1;
p ->next = (*single_list)->next;
(*single_list)->next = p;
}
}
单链表的删除
1 声明一结点p和q,q用来下一个存储删除结点的地址。
2 将头结点地址赋给p
3 循环:
将下一个结点地址赋给q保存
释放p的空间
把q的地址给p;
Status SingleListCreate(LinkList *single_list)
{
LinkList q,p;
p = (*single_list) ->next;
while(p)
{
q = p->next;
free(p);
p = q;
}
(*single_list) ->NULL;
return OK;
}