数据结构——链表
1、由数组实现的链表
定义一个结构体为链表,然后该结构体内有一个数组来存储内容,其他的标识符来表明链表的信息,比如:定义长度来表示链表现在的长度。
struct LinkList
{
int value[MAX];
int length;
};
链表的几个常用操作:
1)得到某个位置的数据
int getElem(LinkList linklist,int pos)
{
if(pos-1>=0&&pos-1<linklist.length)
return linklist.value[pos-1];
return 0;
}
2)插入操作
int insrtLinkList(LinkList *linklist,int pos,int elem)
{
if(linklist->length==MAX||pos<1)
return 0;
else
{
for(int i=linklist->length-1; i>=pos-1; i--)
linklist->value[i+1]=linklist->value[i];
linklist->value[pos-1]=elem;
linklist->length++;
return 1;
}
}
3)删除操作
int deleteLinkList(LinkList *linklist,int pos)
{
if(linklist->length==0||pos>linklist->length)
return 0;
else
{
int elem;
elem=linklist->value[pos-1];
for(int i=pos-1;i<linklist->length;i++)
linklist->value[i]=linklist->value[i+1];
linklist->length--;
return elem;
}
}
因为我们使用数组来存储数据,在获得某个位置的数据时,可以非常方便的使用数组的下标来实现,但是当我们进行删除和添加的操作时,我们会发现,无论是删除一个数据还是添加一个数据都要将该位置以后的数据进行移动,这样就浪费了很多的时间。
试想,我们可以在链表的每个节点处增减一个标识符来指示其下一个数据的位置,这样我们在进行删除和添加的时候我们就不必移动数据,我们所要做的就是修改该标识符,这样可以为我们节约时间。这就是静态链表!
2、静态链表
定义结构体
struct Node
{
int value;
int cur;
};
当我们进行数据的添加时,我们需要为该数据分配一个空间,因为我们的链表在操作过程中,可能已经不再是连续的数组元素,为了尽量的节约空间所以我们应该记录下空闲元素的位置,然后进行分配。
int mallocLinkList(Node *linklist)
{
int i=linklist[0].cur;
linklist[0].cur=linklist[i].cur;
return i;
}
int insertLinkList(Node *linklist,int pos,int elem)
{
int length=lengthLinkList(linklist);
if(pos<1||pos>length+1)
return 0;
else
{
int k=MAX-1;
int j=mallocLinkList(linklist);
cout<<j<<endl;
linklist[j].value=elem;
int count=1;
int i;
for(i=linklist[MAX-1].cur;count<pos-1;i=linklist[i].cur)
{
count++;
}
linklist[j].cur=linklist[i].cur;
linklist[i].cur=j;
return 1;
}
}
同样的当我们进行数据删除的时候,我们也应动态的将删除后的空闲空间添加至我们的空闲空间中去。
<pre class="cpp" name="code">int freeLinkList(Node *linklist,int pos)
{
linklist[pos].cur=linklist[0].cur;
linklist[0].cur=pos;
}
int deleteLinkList(Node *linklist,int pos)
{
int length=lengthLinkList(linklist);
if(pos<1||pos>length)
return 0;
else
{
int i;
int count=1;
for(i=linklist[MAX-1].cur;count<pos-1;i=linklist[i].cur)
count++;
int temp=linklist[i].cur;
linklist[i].cur=linklist[temp].cur;
freeLinkList(linklist,temp);
return 1;
}
}
3、动态链表
在静态链表中,我们使用cur标识符来表示下一个相邻数据的下标时,我们会发现这和指针是多么的相似,为什么我们不能使用指针来完成链表的操作呢?这就是动态链表!
数据结构
struct Node
{
int value;
Node *next;
};
添加操作
void insertLinkList(Node *LinkList,int pos,int elem)
{
Node *cur=LinkList;
int i=1;
while(cur&&i<pos)
{
cur=cur->next;
i++;
}
if(!cur||i>pos)
cout<<"insert failed"<<endl;
else
{
cout<<"insert successed"<<endl;
Node *newNode =new Node();
newNode->value=elem;
newNode->next=cur->next;
cur->next=newNode;
}
}
删除操作
int deleteLinkList(Node *LinkList,int pos)
{
Node *cur=LinkList;
int i=1;
while(cur&&i<pos)
{
cur=cur->next;
i++;
}
if(!cur||i>pos)
cout<<"delete failed"<<endl;
else
{
cout<<"delete success"<<endl;
Node *temp=cur->next;
cur->next=cur->next->next;
delete(temp);
}
}
利用指针操作时,我们会发现delete()\new()和在静态链表里面写的malloc_LinkList\free_LinkList是类似的。
由此可见我们使用指针的操作使得操作更加简单快捷,但是当我们使用一些没有指针的的语言的时候,为了使用更加高效的链表,静态链表无疑是最好的选择!
当然有些高级语言已经实现了List的各种操作......