单链表
线性表的链式存储结构的是用一组任意的存储单元存储线性表的数据元素.这组存储单元可以是连续的,也可以是不连续的.
数据域:存储数据元素信息的域。
指针域:存储直接后继位置的域。
这两部分信息组成数据元素的存储映像,成为节点(Node)。
n 个结点链接成一个链表,即为线性表(a1,a2,a3…….an)的链式存储结构。,有因为此链表的每个结点只含有一个指针域,故称单链表。图(1)
头指针:链表中第一个结点的存储位置。
线性表的最后一个结点指针为空(NULL).图(2)
但是有时为了简便插入,删除等操作,特意在单链表的第一个结点前附设一个结点,成为头结点。头节点的指针域存储指向第一个结点的指针。即存储头指针。
头结点与头指针的异同:如图(3)
带有头节点的单链表:图(4)
空链表:图(5)
单链表的存储结构定义:图(6)
单链表的插入操作:图(7)
如图:在结点p后面插入一个新的结点s。只需操作:
s->next = p->next;
p->next = s;
对于单链表的表头与表尾操作是相同的。图8
单链表的删除:图(9)
如上图:将结点ai删除。
P->next = ai; q = ai;
操作步骤:
q = p->next;
p->next = q->next; 顺序不可更改。
单链表结构与顺序存储结构的优缺点:
/*****************************************************代码实现**************************************************************/
typedef int Status;
typedef int ElemType;
typedef struct Node //定义节点
{
ElemType data;
struct Node *next;
}Node;
typedef struct Node *LinkList; //定义链表
Status Vist(ElemType e)
{
printf("%3d",e);
return OK;
}
/*
****操作结果:对链表进行初始化,建立带头节点的链表
*/
Status InitList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(Node));
if(!(*L))
return ERROR;
(*L)->next = NULL;
return OK;
}
/*
****初始条件:链表L已经存在
****操作结果:若L为空表,则返回TRUE,否则返回FALSE
*/
Status EmptyList(LinkList L)
{
if(L->next)
return FALSE;
else
return TRUE;
}
/*
****初始条件:链表L已经存在
****操作结果:将L置为空表
*/
Status ClearList(LinkList *L)
{
LinkList p,q;
p = (*L)->next;
while(p) //没到表尾
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL; //头结点指针域为空
return OK;
}
/*
****初始条件:链表L已经存在
****操作结果:返回L的长度,即元素个数
*/
Status LengthList(LinkList L)
{
int i = 0;
LinkList p = L->next;
while(p)
{
i++;
p = p->next;
}
return i;
}
/*
****总结:find0 输入k: i = 0 , p = L; 输出:第k个结点值
******** find1 输入k: i = 0 , p = L->next; 输出:第k+1个结点值
******** find2 输入k: i = 1 , p = L; 输出:第k-1个结点值
******** find3 输入K: i = 1 , p = L->next; 输出:第k个结点值
*/
int Find0(LinkList L,int k)
{
int i = 0;
ElemType e;
LinkList P;
P = L;
if(L == NULL || k == 0 )
return ERROR;
while(P && i < k)
{
if(P->next != NULL)
P = P->next;
i++;
}
e = P->data;
return e;
}
//输出第k+1个结点值
int Find1(LinkList L,int k)
{
int i = 0;
int j = LengthList(L);
ElemType e;
LinkList P;
P = L->next;
if(L == NULL || k == 0 || k > j)
return ERROR;
while(P && i < k)
{
P = P->next;
i++;
}
e = P->data;
return e;
}
//查找元素 输出为K-1 ,i = 1,p = L
int Find2(LinkList L,int k)
{
int i = 1;
int j = LengthList(L);
ElemType e;
LinkList P;
P = L;
if(L == NULL || k == 0 || k > j)
return ERROR;
while(P && i < k)
{
P = P->next;
i++;
}
e = P->data;
return e;
}
//查找元素 输出为K, i = 1,p = L->next
int Find3(LinkList L,int k)
{
int i = 1;
int j = LengthList(L);
ElemType e;
LinkList P;
P = L->next;
if(L == NULL || k == 0 || k > j)
return ERROR;
while(P && i < k)
{
P = P->next;
i++;
}
e = P->data;
return e;
}
//查找链表尾部元素
int FindTailList(LinkList L)
{
ElemType e;
LinkList P = L; //L链表为带头指针的。空时,L->next == NULL
LinkList Q = P->next;
if(L->next == NULL)
return 0;
while(P && Q->next != NULL)
{
P = P->next;
Q = Q->next;
}
e = Q->data;
return e;
}
/*
***初始条件:链表L已经存在,1<=i<=LengthList(L)
***操作结果:用e返回第i个数据元素的值
*/
Status GetElem(LinkList L ,int i,ElemType *e)
{
int j = 1;
LinkList p;
p = L->next; //指向链表的第一个结点
//是否判断L是否存在,以及i==0呢?
while(p && j<i) //找到第i个数据元素
{
p = p->next;
j++;
}
if(!p || j>i)
return ERROR;
*e = p->data;
return OK;
}
/*
****初始条件:链表L已经存在
****操作结果:返回L中第一个与e满足关系的元素位序
*/
int LocateElem(LinkList L,ElemType e)
{
int i = 0;
LinkList p;
p = L->next;
while(p)
{
i++;
if(p->data == e)
return i;
p = p->next;
}
return 0;
}
/*
****初始条件:链表L已经存在
****操作结果:在线性表的第i个位置之前插入新的数据元素,长度加1
*/
Status InsertList(LinkList *L,int i,ElemType e)
{
int j = 1;
LinkList p ,s;
p = *L;
while(p && j<i) //找到第i-1个结点
{
p = p->next;
j++;
}
if(!p || j>i)
return ERROR;
s = (LinkList)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
/*
****初始条件:链表L已经存在
****删除链表的第i个数据元素,并用e返回其值,长度减一
*/
Status DeleteList(LinkList *L,int i,ElemType *e)
{
int j = 1;
LinkList p,q;
p = *L;
while(p && j<i)
{
p = p->next;
j++;
}
if(!p || j>i)
return ERROR;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
/*
****初始条件:链表L已经存在
****操作结果:输出每个结点的值
*/
Status TraverseList(LinkList L)
{
LinkList p = L->next;
while(p)
{
Vist(p->data);
p = p->next;
}
printf("\n");
return OK;
}
/*
****
****操作结果:随机产生n个数值,建立头插法的链表
*/
void CreateHeadList(LinkList *L,int n)
{
int i;
LinkList p;
srand(time(0));
(*L) = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;
for(i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = rand()%100+1;
p->next = (*L)->next;
(*L)->next = p;
}
}
/*
****
****操作结果:建立尾插法的链表
*/
void CreateTailList(LinkList *L,int n)
{
int i;
LinkList p,tail;
srand(time(0));
(*L) = (LinkList)malloc(sizeof(Node)); //建立链表
tail = *L; //尾指针,初始指向链表L的头指针
for(i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = rand()%100+1;
tail->next = p; //在尾部插入新的结点
tail = p; //尾指针tail指向新的尾结点
}
tail->next = NULL;
}
/*
****初始条件:链表L已经存在
****操作结果:对单链表进行递增排序
****说明:使用的“蛮力法”,复杂度较高。可以用经典排序算法处理。后面会写到。
*/
void SortList(LinkList *L)
{
LinkList p,q;
p = (*L)->next;
while(p->next)
{
q = p->next;
while(q)
{
if(q->data < p->data)
{
int temp = q->data;
q->data = p->data;
p->data = temp;
}
q = q->next;
}
p = p->next;
}
}