在数据结构与算法的学习中,首先要了解ADTS(abstract data types),ADTS是一种抽象的数据类型,它是为了解决某个问题而自行设计的数据类型,它既包括数据也包括操作。下面是三种基本ADTS,即List、Stacks、Queues。
ADTS与int,float,array,pointer等基本数据类型的区别主要是ADTS不仅是多个相同基本数据类型的集合,而且它定义了自身集合的某些操作。
Lists:Lists的定义既可以用数组,也可以用指针。用数组的话,其主要缺点是浪费空间,因为数组定义时其容量Max会给定,而且其在内存存储中需要连续的一块内存;而如果用指针的话,就比较简单,但在某些操作上其时间复杂度就比用数组的大,下面的分析,我主要使用指针。
相关操作的实现
定义:
<span style="font-size:18px;">struct Node
{
ElemType data;
struct Node *next;
};
typedef struct Node *List,*Position;</span>
判断列表是否为空
<span style="font-size:18px;">int IsEmpty(List L)
{
return L->next==NULL;panduan
}</span>
判断是否为最后一个结点
<span style="font-size:18px;">int IsLast(Position P,List L)
{
return P->next==NULL;
}</span>
返回数值为X的元素的位置,注意这里是指返回第一个值为X的位置
<span style="font-size:18px;">Position Find(ElemType X,List L)
{
Position P;
P=L->next;
while(P!=NULL&&P->data!=X)
{
P=P->next;
}
return P;
}</span>
寻找元素的前驱结点
<span style="font-size:18px;">Position FindPrevious(ElemType X,List L)
{
Position P;
P=L;
while(P->next!=NULL&&P->data!=X)
{
P=P->next;
}
return P;
}</span>
删除元素
<span style="font-size:18px;">void Delete(ElemType X,List L)
{
Position P;
Position TmpCell;
//首先判断L是否为空
if(!IsEmpty(L))
{
P=FindPrevious(X,L);
//此处要考虑P为最后一个结点的数据
if(!IsLast(P,L))
{
TmpCell=P->next;
P->next=TmpCell->next;
free(TmpCell);
}
}</span>
插入数据
<span style="font-size:18px;">void Insert(ElemType X,List L,Position P)
{
Position TmpCell;
TmpCell=(Position)malloc(sizeof(Node));
TmpCell->data=X;
if(TmpCell!=NULL)
{
TmpCell->next=P->next;
P->next=TmpCell;
}
}</span>
<span style="font-size:18px;">//创建一个列表
//创建的方法有头插法和尾插法
//头插法</span>
<span style="font-size:18px;">void CreateListHead(List L,int n)
{
Position TmpCell;
int i=0;
while(i<n)
{
TmpCell =(List)malloc(sizeof(Node));
TmpCell->data=i++;
TmpCell->next=L->next;
L->next=TmpCell;
}
}
void CreateListTail(List L,int n)
{
Position TmpCell,P;
P=L;
int i=0;
while(i<n)
{
TmpCell=(List)malloc(sizeof(Node));
TmpCell->data=i++;
P->next=TmpCell;
P=TmpCell;
}
P->next=NULL;
}
void PrintList(List L,int n)
{
Position P;
P=L->next;
int i=0;
while(i<n)
{
int data=P->data;
P=P->next;
cout<<data<<" ";
i++;
}
}
</span>
以上代码是关于如何打印一个列表的函数
原本在写代码的时候我还在想如果在尾部插入的话,会不会需要分类讨论,但是即使是尾部也需要将NULL指针复制给TmpCell,因此不需要讨论P是否为最后一个结点。
此外要特别注意下头结点这个基本概念,它也是个Node,只是它的数据域没有意义,即不赋值,是随机的,而它的指针域是指向第一个结点