一、线性表链式存储结构
1、特点:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。也就是说这些数据元素可以存在内存没有被占用的任意位置。
2、节点由数据域和指针域组成。其中数据域存放数据元素,指针域存放后继节点的地址。
3、头指针与头节点的区别:
(1)头指针是链表指向第一个节点的指针,如果链表有头节点,则是指向头节点的指针;并且无论链表是否为空,头指针都不为空。
(2)头节点是放在第一元素节点之前的节点,数据域一般无意义,头节点不一定是链表的必要元素。
4、注意:
(1)在整个链表中,只有头节点有名字,其他数据节点没有名字,需要通过指针来访问;
(2)空链表没有数据节点,但是有头节点;
(3)销毁链表时不需要销毁头节点;
二、线性链表的抽象数据结构
#include<stdio.h>
#include<stdlib.h>
#include maxsize 1000
typedef struct node
{
int data[maxsize];
struct Node *next;
}Node;
typedef struct Node *Linklist;
1、单链表
1.1单链表的读取
int GetElem(Linklist L,int i,int *e)
{
//L是带有头节点的单链表的头指针
//当第i个元素存在时,赋值给e并返回1,否则返回0
Linklist p;//声明指针
int j=1;//用于计数
p=L->next;//初始化,p指向链表的第一个节点
while(p && j<=i)
{
p=p->next;
++j;
}
if(!p || j>i )
return 0;
*e=p->data;//取第i个节点的数据值
return 1;
}
1.2单链表的插入
在链表L的第i个位置之前插入数据e,L长度增加1
int InsertElem (Linklist *L,int i,int e)
{
Linklist p,s;//声明指针(变动指针和插入数据的指针)
p = *L;//p指向链表的头指针
int j=1;//计数
while(p && j<i)
{
//寻找第(i-1)个节点位置,就是要插入数据的位置
p = p->next;
++j;
}
if(!p || j>i)
return 0;
s=(Linklist)malloc(sizeof(Node));//生成新节点
s->data=e;//找到位置,数据赋值
s->next=p->next;//重点!
p->next=s;//顺序不能错!
return 1;
}
1.3单链表的删除
将链表L第i个节点删除,用e返回其值,L长度减1
int DelElem(Linklist *L,int i,int *e)
{
Linklist p,q;//声明指针(变动指针和要删除的指针)
int j=1;//计数
p=*L;//指向链表的头指针
while(p && j<i)//寻找第i-1个节点
{
p=p->next;
++j;
}
if(!p || j>i)
return 0;
q=p->next;
p->next=q->next;
*e=q->data;
free(q);
return 1;
}
1.4单链表的整表创建
方法一:头插法(后插入的在前面)
int CreateAll1(Linklist *L,int n)
{
Linklist p;
int i;
*L=(Linklist)malloc(sizeof(Node));
(*L)->next=NULL;//建立带头节点的单链表
for(i=0;i<n;i++)
{
p=(Linklist)malloc(sizeof(Node));//生成新节点
scanf("%d",&p->data);//输入数据
p->next=(*L)->next;//重点!
(*L)->next=p;//顺序不能错,和单链表的插入类似
}
}
方法二:尾插法(后插的在后面)
int CreateAll2(Linklist *L,int n)
{
Linklist p,r;
int i;
*L=(Linklist)malloc(sizeof(Node));
r=*L;//r是指向尾部的节点
for(i=0;i<n;i++)
{
p=(Linklist)malloc(sizeof(Node));
scanf("%d",&p->data);
r->next=p;//将尾节点的指针域设置为新节点
r=p;//更新尾部节点
}
r->next=NULL;//表示当前链表结束
}
1.5单链表的整表删除
/*单链表的整表删除*/
int DelAll(Linklist *L)
{
Linklist p,q;
p=(*L)->next;//指向第一个节点
while(p)
{
q=p->next;//将下一个节点赋值给q
free(p);//释放当前节点
p=q;//达到循环释放
}
(*L)->next=NULL;//头节点的指针域为空
return 1;
}