单链表基本操作的实现
链式存储相关术语
数据域:存储数据元素信息的域。
指针域:存储直接后继位置的域。
结点:数据元素的存储映像,由数据域和指针域组成。
链表:n个结点链结成一个链表。即线性表的链式存储结构。
单链表:结点只有一个指针域的链表。
头指针:指向链表第一个结点的指针。
头结点:单链表第一个结点前附设的一个结点。
头结点是为了操作的统一与方便设立的,如在第一元素结点前插入结点与删除第一结点。
单链表结构与顺序存储结构的比较
注意:顺序表为随机存取结构,链表为顺序存取结构。
顺序存取结构:访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其余结点,所以寻找第一结点和最后一个结点所耗费时间不同。这种存取元素的方法称为顺序存取。
- | 顺序存储结构 | 单链表 |
---|---|---|
查找 | 时间复杂度O(1) | 时间复杂度O(n) |
插入和删除 | 平均移动表长一半的元素,时间复杂度为O(n) | 找出位置的指针后,时间复杂度为O(1) |
空间性能 | 需预分配储存空间,易溢出 | 不需分配储存空间,元素个数不受限制 |
• 若线性表需频繁查找,插入与删除操作少,宜用顺序存储结构
• 线性表元素个数变化大或不知道多大时,最好用单链表结构
基本操作实现
单链表的定义
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef int ElemType;
typedef struct Lnode {
ElemType data;
struct Lnode *next;
} Lnode;
typedef struct Lnode *LinkList;
初始化链表
/* 初始化链表 */
Status InitList(LinkList *L) //二级指针
{
*L = (LinkList)malloc(sizeof(Lnode));
(*L)->next = NULL;
return OK;
}
判断链表是否为空
/* 判断链表是否为空 */
Status ListEmpty(LinkList L)
{
if (L->next) return 0; //非空
else return 1;
}
求表长
/* 求表长 */
Status ListLengh(LinkList L)
{
LinkList p;
p = L->next;
int i = 0;
while (p)
{
p = p->next;
i++;
}
return i;
}
清空链表
/* 清空链表 */
Status ClearList(LinkList* L)
{
LinkList p, q;
p = (*L)->next;
while (p)
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL; //头结点指针域为空
return OK;
}
销毁单链表
/* 销毁单链表 */
Status DestroyList(LinkList* L)
{
LinkList p = *L;
while (p)
{
*L = (*L)->next;
free(p);
p = *L;
}
return OK;
}
单链表的取值
/* 单链表的取值 */
Status GetElem(LinkList L, int i, ElemType *e)
{
LinkList p = L->next;
int j = 1;
while (p && j < i)
{
p = p->next;
j++;
}
if (!p || j > i) return ERROR;
*e = p->data;
return OK;
}
查找
/* 按值查找 返回地址*/
LinkList LocateELem(LinkList L, ElemType e)
{
LinkList p = L->next;
while (p && p->data != e)
p = p->next;
if (p) return p;
else
return NULL;
}
/* 按值查找 返回位序*/
Status LocateELem_(LinkList L, ElemType e)
{
LinkList p = L->next;
int j = 1;
while (p && p->data != e)
{
p = p->next;
j++;
}
if (p) return j;
else
return 0;
}
插入 在L中第i个位置之前插入新的数据元素e
/* 插入 在L中第i个位置之前插入新的数据元素e*/
Status Listlnsert(LinkList*L, int i, ElemType e)
{
int j = 0;
LinkList p = *L;
while (p && j < i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1) return ERROR;
LinkList pnew = (LinkList)malloc(sizeof(Lnode));
pnew->data = e;
pnew->next = p->next;
p->next = pnew;
return OK;
}
删除第i个元素
/* 删除第i个元素*/
Status ListDelete(LinkList* L, int i, ElemType* e)
{
int j = 0;
LinkList p = *L;
while (p && j < i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1 || !p->next) return ERROR;
LinkList pfree = p->next;
*e = pfree->data;
p->next = pfree->next;
free(pfree);
return OK;
}
单链表的建立 头插法
/* 头插法 */
void CreateList(LinkList *L, int i)
{
int j;
for (j = 0; j < i; j++)
{
LinkList p = (LinkList)malloc(sizeof(Lnode));
int data;
scanf("%d", &data);
p->data = data;
p->next = (*L)->next;
(*L)->next = p;
}
}
单链表的建立 尾插法
/* 尾插法 */
void CreateList_(LinkList *L, int i)
{
LinkList ptail = *L;
int j;
for (j = 0; j < i; j++)
{
LinkList pnew = (LinkList)malloc(sizeof(Lnode));
int data;
scanf("%d" ,&data);
pnew->data = data;
pnew->next = NULL;
ptail->next = pnew;
ptail = pnew;
}
}