线性链表与顺序表的区别在于存储的结构不同,顺序表是物理位置相邻,逻辑也相邻,而链表物理位置不一定相邻但是逻辑相邻,这导致他查找,存取数据时需要一一遍历以找到所需要存取的位置,因为链表的相邻,相当于我不知道你具体在哪里,我只能看到前面和后面的人,若要找到某个人,就得一个一个问过去。基于链表的基本知识,我们可以创建这样一个链表。
-
创建链表
先创建结点结构体,和上篇文章一样,我们仍然使用ElemType来作为我们数据类型的别名,前篇文章链接如下:
https://blog.csdn.net/xiaoyan4869/article/details/142053966
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
以下是头插法创建单链表的代码
注意头插法输入数据需要倒序
void CreatList_L(LinkList &L,int n){
//逆位数输入n个元素的值,建立带表头节点的单链线性表L
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL; //先建立一个带头节点的单链表
for(int i=n;i>0;i--){
LNode p=(LinkList)malloc(sizeof(LNode)); //生成新结点
scanf("%?",&p->data); //问号中的字符由输入值的类型决定
p->next=L->next; //新节点的下一个节点是头节点后的一个结点
L->next=p; //头结点链接新节点
}
-
查找结点
查找第i个结点,需要一个个顺序向后遍历,用j进行计数,记录遍历过的结点数量,然后用e来返回查到结点的元素值
Status GetElem_L(LinkList &L,int i,ElemType &e){
LNode *p=L->next; //从第一个存储数据的结点开始查找
int j=1;
while(p && j<i){
p=p->next; //遍历链表并计数找到第i个结点
++j;
}
if(!p || i>j)
return ERROR; //遍历到非法位置后返回error
e=p->data; //找到了i位置的数后赋值给e
return OK;
}
-
删除
结点
如下图所示,删除结点只需要遍历到被删除结点的上一个位置,然后使上一个位置的结点链接到被删除结点的下一个位置就完成了。
Status ListDelete_L(LinkList &L,int i,ElemType &e){
//在带头结点的单链表中删除第i个数并将删除的数返回e
int j=0;
LNode *p=L;
while(!p && j<i-1){ //寻找第i-1个结点
p=p->next;
}
LNode q=p->next; //q等于p的下一个结点
p->next=q->next; //p的下一个结点等于q的下一个节点
e=q->data; //e的值为被删除的值
free(p); //释放被删除的结点
}
-
插入结点
如图是插入结点的示意图
插入结点的关键点在于先链接插入位置的后一个结点,以防止后续结点丢失,然后再链接前一个结点
Status LinkInsert_L(LinkList &L,int i,ElemType &e){
//在带头结点的单链线性表L中第i个位置前插入元素e
LNode p=L,q;
int j=0;
while(p && j<i-1){ //找到第i-1个结点
p=p->next;
j++;
}
if(!p || j>i-1) return ERROR;
q=(LinkList)malloc(sizeof(LNode)); //创建新节点
q->data=e;
q->next=p->next;
p->next=q;
return OK;
}
-
合并链表
已知顺序表La和Lb的元素按值非递减排列,归并La和Lb得到新的顺序表Lc,Lc的元素也按值非递减排列
void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
pa=La->next; //pa,pb均指向两个链表的第一个元素
pb=Lb->next;
Lc=pc=La;
while(pa && pb){ //逐个从La,Lb中一一取出元素,比较得出较小的元素值,放入新链表中
if(pa->data <= pb->data){
pc->next = pa;
pc = pa;
pa = pa->next;
}
else{
pc->next = pb;
pc = pb;
pb = pb->next;
}
pc->next = pa?pa:pb; //将La,Lb中剩余的元素放入链表c
free(Lb);
}
链表比起顺序表,虽然查找,存取数据时间复杂度较高,必须逐个遍历才能找到指定的数据,但是优点也很突出,就是不需要连续的地址空间,也便于插入数据删除数据,只要改变指针指向就足够了,不需要一个一个后移数据,大大节省了时间。