一、链表
1.顺序表的基本操作
(1).初始化(构造一个空的顺序表)
Status InitList(SqList &L)
{
L.elem=new ElemType[MAXSIZE];//为顺序表分配一个大小为MAXSIZE的数组空间
if(!L.elem)
exit(OVERFLOW);
L.length=0;
return OK;
}
(2).取值
【算法步骤】
1.判断指定的位置序号i值是否合理(1<=i<=L.length),若不合理,则返回ERROR。
2.若i值合理,则将第i个数据元素L.elem[i-1]赋给参数e,通过e返回第i个数据元素的传值
Status GetElem(SqList L,int i,ElemType &e)
{
if(i<1||i>L.length)
{return ERROR;}
e=L.elem[i-1];
return OK;
}
(3).查找
int LocateElem(SqList L,ELemType e)
{
for(i=0;i<L.length;i++)
{
if(L.elem[i]==e)
{return i+1;}
}
return 0;
}
(4).插入
【算法步骤】
1.判断插入位置是否合理,若不合理则返回ERROR
2.判断顺序表的存储空间是否已满,若满则返回ERROR
3.将第n个至第i个位置的元素依次向后移动一个位置,空出第i个位置(i=n+1时无需移动)
4.将要插入的新元素e放入第i个位置
5.表长加一
Status Listinsert(SqList &L,int i,ElemType e)
{
if((i<1)||(i>L.length+1))
{return ERROR;}
if(L.length==MAXSIZE)
{return ERROR;}
for(j=L.length-1;j>i;j--)
{
L.elem[j+1]=L.elem[j];
}
L.elem[i-1]=e;
L.length++:
return OK;
}
(5).删除
Status ListDelete(SqList &L,int i)
{
if((i<1)||(i>L.length))
{return ERROR;}
for(j=i;j<=L.length-1;j++)
{
L.elem[j-1]=L.elem[j];
}
--L.length;
return OK;
}
2.单链表(线性链表)
单链表的存储结构
typedef struct node
{
ElemType data;//结点的数据域
struct node *next;//结点的指针域
}node,*LinkList;//LinkList为指向结构体node的指针类型
单链表的基本操作
(1).初始化
【算法步骤】
1.生成新结点为头结点,用头指针L指向头结点
2.头结点的指针域置空
Status InitList(LinkList &L)
{
L=new node;
L->next=NULL;
return OK;
}
2.取值
Status GetElem(LinkList L,int i,ElemType &e)
{//在带头结点的单链表L中根据序号i获取元素的值,用e返回L中第i个数据元素的值
p=L->next;
j=1;
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i)
return ERROR;
e=p->data;
return OK;
}
3.查找
【算法步骤】
①用指针p指向首元结点。
②从首元结点开始依次顺着链域next向下查找,只要指向当前结点的指针p不为空,并且p所指结点的数据域不等于给定值e,则循环执行以下操作: p指向下-个结点。
③返回p。若查找成功,p此时指向结点的地址值,若查找失败,则p的值为NULL。
node *LocateElem(LinkList L,ElemType e)
{
p=L->next;//初始化
while(p&&p->data!=e)
{
p=p->next;
}
return p;
}
4.插入
【算法步骤】
将值为e的新结点插入表的第i个结点的位置,即插入结点ai-1与ai之间,如图所示:
1.查找结点ai-1并由指针p指向该结点
2.生成一个新结点*s
3.将新结点*s的数据域置为e
4.将新结点*s的指针域指向结点ai
5.将结点*p的指针域指向新结点*s
【算法描述】
Status ListInsert(LinkList &L,int i,ElemType e)
{
p=L;j=0;
while(p&&(j<i-1))//查找第i-1个结点,p指向该结点
{p=p->next;j++;}
if(!p||j>i-1)
{return ERROR;}
s=new node;
s->data=e;//将结点*s的数据域置为e
s->next=p->next;//将结点*s的指针域指向ai
p->next=s;//将结点*p的指针域指向结点*s
return OK;
}
5.删除
Status ListDelete(LinkList &L,int i)
{
p=L;j=0;
while((p->next)&&(j<i-1))
{p=p->next;++j;}
if(!(p->next)||(j<i-1))
return ERROR;
q=p->next;//临时保存被删除结点的地址以备释放
p->next=q->next;//改变删除结点前驱结点的指针域
delete q;
return OK;
}
6.创建单链表
(1)前插法
void createList_H(LinkList &L,int n)
{
L=new node;
L->next=NULL;
for(i=0;i<n;i++)
{p=new node;
scanf("%d",&p->data);
p->next=L->next;
L->next=p;
}
}
(2).后插法
void createList_R(LinkList &L,int n)
{
L=new node;
L->next=NULL;
r=L;
for(i=0;i<n;i++)
{p=new node;
scanf("%d",&p->data);
p->next=NULL;r->next=p;//将新结点*p插入尾结点*r之后
r=p;//r指向新的尾结点*p;
}
}
以上讨论的链式存储结构的结点中只有-个指示直接后继的指针域,由此,从某个结点出发只能顺指针向后寻查其他结点。若要寻查结点的直接前驱,则必须从表头指针出发。换句话说,在单链表中,查找直接后继的执行时间为O(1),而查找直接前驱的执行时间为O(n)。为克服单链表这种单向性的缺点,可利用双向链表。
顾名思义,在双向链表的结点中有两个指针域,一个指向直接后继,另一个指向直接前驱。
存储结构
typedef struct DULnode
{
ELemType data;
struct DuLnode *prior;
struct DuLnode *next;
}DuLnode,*DULinkList;
插入
Status ListInsert_DuL(DULinkList &L,int i,ELemType e)
{
if(!(p=GetElem_DUL(L,i))
return ERROR;
s=new DuLnode;
s->data=e;
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;
return OK;
}
删除
Status ListDelete_DUL(DuLinkList &L,int i)
{
if(!(p=GetElem_DUL(L,i)))
return ERROR;
p->prior->next=p->next;//修改被删除结点的前驱结点的后继指针
p->next->prior=p->prior;//修改被删结点的后继结点的前驱指针
delete p;
return OK;
}
因为比较喜欢写专题,别的今天学的就不写在博客上了