重新定义线性链表及其基本操作
回顾之前:结点和单链表的C语言描述
https://blog.csdn.net/shcolinia/article/details/121974721
//------线性表的单链表存储结构------
typedef struct LNnode
{
Elemtype data;//数据域
struct LNnode *next; //指针域
} LNode,*LinkList;
//L为单链表的头指针
LinkList L;
用之前定义的单链表实现线性表操作时,存在如下问题:
1.单链表的表长是一个隐含的值;
2.在单链表的最后一个元素后插入元素时,需遍历整个链表;
3.在链表中,元素的“位序”概念淡化,结点的“位置”概念加强;
为改进这些问题,我们可进行如下设置:
1.增加“表长”“表尾指针”“当前位置的指针”三个数据域
重新定义线性链表 代码如下:
//一个带头结点的线性链表类型定义
typedef struct LNode//结点类型
{
Elemtype data;
struct LNode *next;
}*Link,*Position;
typename struct//链表类型
{
Link head,tail;//分别指向链表中的头结点和最后一个结点的指针
int len;//指示线性链表数据元素的个数
Link current;//指向当前被访问的结点的指针,初始位置指向头结点
}Linklist;
链表的基本操作有:
应用这些基本操作,容易实现插入元素、删除元素、合并两个线性表等操作。
例1插入操作
//插入操作
Status ListInsert_L(LinkList &L,int i,ElemType e)
//带头结点的但来年线性表L的第i个元素之前插入元素e
{
if(!LocatePos(L,i-1,h)) return ERROR;//i值不合法
//locatepos:返回h指示线性链表L中第i-1个结点的位置
if(!MakeNode(s,e)) return ERROR;//结点存储分配失败
//makenode:分配由s指向值为e的结点
InsFirst(h,s);//对于第i个结点开始的链表,第i-1个结点是它的头结点;
//已知h指向线性链表的头结点,将s所指结点插入第一个结点之前
return OK;
}
例2重点 合并线性表操作
//合并操作
Status MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc
int(*compare)(ElemType,ElemType))
//已知La、Lb的元素按值非递减排列
//归并La、Lb得到新的链表Lc、Lc的元素也按值非递减排列
{
if(!InitList(Lc)) return ERROR;//存储空间分配失败
ha=GetHead(La);
hb=GetHead(Lb);//ha\hb分别指向La和Lb的头结点
pa=NextPos(La,ha);
Pb=NextPos(Lb,hb);//pa、pb分别指向La和Lb中当前结点
while(pa&&pb)/e/pa和pb均非空
{
a=GetCurElem(pa);//已知结点,返回结点数据元素的值
b=GetCurElem(pb);//a和b为两表当前比较元素
if((*compare)(a,b)<=0)//a<=b
{
DelFirst(ha,q);
Append(Lc,q);
pa=NextPos(La,ha);
}
else
{
DelFirst(hb,q);
Append(Lc,q);
pb=NextPos(Lb,hb);
}
}
if(pa) Append(Lc,pa);//链接La剩余结点
else Append(Lc,pb);//链接Lb剩余结点
FreeNode(Ha);
FreeNode(Hb);//释放La和Lb头结点
return OK;
}