单链表
查找指定位置元素的值:
Status GetElem(LinkList L,int i,ElemType *e)
{
int j;
LinkList p;
j = 1;
while(p && j<i)
{
p = p->next;
++j;
}
if(!p || j>i)
{
return ERROR;
}
*e = p->data;
return OK;
}
单链表的插入:
Status ListInsert(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,s;
p = *L;
j = 1;
while(p && j<i) //用于寻找第i个结点
{
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;
}
单链表的删除:
Status ListDelete(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,q;
p = *L;
j = 1;
while(p->next && j<i) //用于寻找第i个结点
{
p = p->next;
++j;
}
if(!(p->next) || j>i)
{
return ERROR;
}
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
头插法建立单链表:
void CreateListHead(LinkList *L,int n)
{
LinkList p;
int i;
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 CreateListTail(LinkList *L,int n)
{
LinkList p,r;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
r = *L;
for(i=0;i < n;i++){
p = (Node *)malloc(sizeof(Node));
p->data = rand()%100+1;
r->next = p;
r = p;
}
r->next = NULL;
}
单链表的整表删除:
Status ClearList(LinkList *L)
{
LinkList p,q;
p = (*L)->next;
while(p)
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL;
return OK;
}
单链表与顺序存储结构优缺点:
存储分配方式:
- 顺序存储需要一段连续的存储单元
- 单链表采用链式存储结构,用一组任意的存储单元即可
时间性能:
- 查找
顺序存储结构O(1)
单链表O(n)
- 插入和删除
顺序存储结构O(n)
单链表O(1)
空间性能:
- 顺序存储结构需要预分配存储空间,可能造成空间的浪费或发生溢出
- 单链表不需要分配存储空间,元素个数也不受限制
若需要频繁查找,很少进行插入删除操作时,适合用顺序存储结构
若需要频繁插入和删除时,适合用单链表结构
静态链表
存储结构:
#define MAXSIZE 1000
typedef struct
{
ElemType data;
int cur;
}Component,StaticLinkList[MAXSIZE];
初始化:
Status InitList(StaticLinkList space)
{
int i;
for( i=0; i < MAXSIZE-1; i++)
{
space[i].cur = i+1;
}
space[MAXSIZE-1].cur = 0;
return OK;
}
插入操作:
//获得空闲分量的下标
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;
if(space[0].cur)
{
space[0].cur = space[i].cur;
}
return i;
}
//插入操作
Status ListInsert(StaticLinkList,int i,ElemType e)
{
int j,k,l;
k = MAX_SIZE-1; //数组的最后一个元素
if(i<1 || i>ListLength(L)+1)
{
return ERROR;
}
j = Malloc_SLL(L);
if(j)
{
L[j].data = e;
for( l=1;l<=i-1;l++)
{
k = L[k].cur;
}
L[j].cur = L[k].cur;
L[k].cur = j;
return OK;
}
return ERROR;
}
删除操作:
Status ListDelete(StaticLinkList L,int i)
{
int j,k;
if(i<1 ||i>ListLength(L))
{
return ERROR;
}
k = MAX_SIZE-1;
for(j=1; j <= i-1;j++)
{
k = L[k].cur;
}
j = L[k].cur;
L[k].cur = L[j].cur;
Free_SLL(L,j);
return OK;
}
//将下标为k的空闲结点回收到备用链表
void Free_SLL(StaticLinkList space,int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
//返回L中数据元素个数
int ListLength(StaticLinkList L)
{
int j = 0;
int i= L[MAXSIZE-1].cur;
while(i)
{
j = L[i].cur;
j++;
}
return j;
}
静态链表优缺点:
优点:
- 插入删除时只需修改游标,不需要移动元素。
缺点:
- 没有解决连续存储分配带来的表长难以确定的问题
- 失去了顺序存储随机存取的特性
单链表面试题
题目:快速找到未知长度单链表的中间结点
思想:快慢指针
Status GetMidNode(LinkList L,ElemType *e)
{
LinkList search,mid;
mid = search = L;
while(search->next != NULL)
{
if(search->next->next != NULL)
{
search = search->next->next;
mid = mid->next;
}else{
search = search->next;
}
}
*e = mid->data;
return OK;
}