版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38041038/article/details/82561120
https://blog.csdn.net/qq_31736627/article/details/52848001(这是关于结构体的一篇较好的博客)
初学者可能会关注如下的内容:
下面是正题。
1、线性表是具有相同数据类型的n个元素的优先序列。
2、线性表的链式存储称为单链表。为了建立线性表之间的线性关系,对每个链表结点,除了存档数据之外,还有一个指向其后继的指针。单链表的结点类型描述如下。
typedef struct LNode{
ElemType data;
LNode * next;
} LNode, *LinkList;
3、线性表上的基本操作
(1)采用头插法建立线性表。(也就是在头结点之后插入)
LinkList CreatList1(LinkList &L){
//每次均在头结点之后建立单链表
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode)); //建立头结点
l->next = null; //初始化为空链表
scanf("%d", &x);
while(x != 9999){
s = (LNode)malloc(sizeof(LNode)); //建立新节点
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d", &x);
}
return L;
}
采用头插法建立单链表,其元素在链表中的顺序与输入顺序是相反的。每个结点的插入时间复杂度为O(1), 所以总的时间复杂度为O(n)。
(2)采用尾插法建立单链表
此时必须需要一个尾指针,其总是指向当前结点的尾结点。
LinkList CreatList2(LinkList &L){
int x;
LNode *s; //要插入结点的指针
L = (LinkList)malloc(sizeof(LNode)); //建立头结点
LNode *r = L; //在最开始,尾指针就指向头结点。
scanf("%d", &x);
while(x != 9999){
s = (LNode)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = null; //尾结点指针为空;
return L;
}
(3)按序号查找结点
返回所需结点的指针,即所需结点的地址。
在单链表中,顺序指针next逐个往下搜需哦,直到查到第i个结点为止。
LNode * GetElm(LinkList L, int i){
int j = 1;
LNode * p = L->next; //从头结点开始检索,将头结点的指针域复给p
if(i = 0)
return L; //头结点是第一个结点,第一个节点之前的第0个结点是头指针所指的结点
if(i < 1)
return NULL;
while(p && j < i){
p = p->next;
j++;
}
return p; //如果i大于表长,那么p = NULL,直接返回即可
}
(4)按值查找
LNode * ElemLocat(LinkList L, ElemType e){
LNode *p = L->next; //将头结点的指针域复制给p
while(p && p->data != e){ //从第一个结点开始
p = p->next
return p;
}
(5)插入节点操作(插入与删除都是先调用GetElem()找到第i个节点的前驱节点,主要的时间开销是查找第i-1个元素,时间复杂度为O(n))。
p = GetElem(L,i - 1); //找到插入位置的前驱节点
s->next = p->next; //把插入节点前驱节点的后继赋值给插入节点后继
p->next = s; //插入节点成为第i-1节点的新后继
(6)删除节点操作
p = GetElme(L, i - 1); //找到删除节点的前驱节点p
q = p->next; //把要删除的节点赋值给q
p->next = q->next; //把q节点从p节点和p->next之间挖掉
free(q); //释放q