1.单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LinkList更倾向于是表示一条链表
LNode *更倾向于表示一个指针
2.采用头插法建立单链表
LinkList List_HeadInsert(LinkList &L){
LNode *s;int x;
L=(LinkList)malloc(sizeof(LNode));//创建头结点;
L->next=NULL;//初始为空链表
scanf("%d",&x);
while(x的条件){//条件看自己的要求设定
S=(LNode*)malloc(sizeof(LNode));//创建要插入的节点
S->data=x;
S->next=L->next;
L->next=S;
scanf("%d",&x);
}
return L;
}
3.采用尾插法建立单链表
头插法虽然简单,但生成的链表中的节点次序和输入顺序不一致.
LinkList List_TailInsert(LinkList &L){
int x;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
LNode *s,*r=L;//r设为表位指针;
scanf("%d",x);
while(x的条件){
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=r->next;
r->next=s;
r=s;
}
return L;
}
相比于头插法就多了一个表尾节点的设定
4.按序号查找节点
LNode *GetElem(LinkList L,int i)
{
if(i<1)//如果i超出了线性表的长度,也返回NULL;
return NULL;
int j=1;
LNode *p=L->next;//第一个节点赋值个p;
while(p!=NULL&&j<i){
p=p->next;
j++;
}
return p;
}
5.按值查找表结点
LNode *LocateElem(LinkList L,ElemType e)
{
LNode *p=L->next;//一般是有头节点才敢这样操作
while(p!=NULL){
if(p->data==e)
return p;
p=p->next;
}
return NULL;
}
6.插入节点操作
插入节点操作时将值为x的节点插入到单链表的第i个位置上,先检查插入位置的合法性,然后找到待插入位置的前驱节点,即第i-1个节点,在再其后面插入新节点s.
算法:首先调用按序好查找算法GetElem(L,i-1),找到第i-1个节点,假设返回的第i-1个节点是*p,
不说了直接看代码得了,说的太抽象了
p=GetElem(L,i-1);
s=p->next;
p->next=s;
搞定.时间复杂度的话查找时间O(n),插入开销为O(1);
7.删除节点操作
假设节点p为被删除节点的前驱节点.......
bool DeleteElem(LinkList &L,int i)
{
if(i<1)//如果i超出了线性表的长度,也返回false;
return false;
int j=1;
LNode *p=L->next;//第一个节点赋值个p;
while(p!=NULL&&j<i-1){
p=p->next;
j++;
}LNode *q=p->next//令q为待删除节点
p->next=q->next;//这就是关键删除
free(q);//肯定要释放这个被删除的东西的存储空间.
}
有一些说法:其实删除节点重要的不是那个节点,而是那个节点的data,所以我只要将那个data去掉,节点长度减一,其顺序不变就行.
q=p->next;
p->data=q->data;
p->next=q->next;
free(q);
相当于删除了P节点的后继节点,本应该删P,但是却删了P的后继,但P的后继的data(火种)传给了P,抽象来说就是P的后继替P被删,只要P答应保存Q的火种.
8.求表长操作
对单链表分两种情况.
有头结点的话:
LNode *p=L->next;
int count=0;
while(p!=NULL){
p=p->next;
j++;
}
return j;
无头结点的话:
int count=0;
LNode *p=L;
while(p!=NULL){
p=p->next;
count++;
}
return count;
作者建议:
听我说,单链表是整个链表结构的基础,请各位一定掌握单链表基本操作,它真的真的很重要,尤其做实验和应付考试.