链式存储结构的特点是使用了一组任意的存储单元存储数据元素,链表中每个元素可以分布在内存中的各个角落,这不是链表所要关心的,即使各个元素在物理位置上相邻,也不会提高链表的工作效率,所以链表是一种完全忽略物理位置而只注重逻辑关系的一种数据结构。这样的数据结构存在着很大的优点,在进行插入或者删除的操作时,无须移动大量的元素,只要改变相应元素的指针就可以,这大大节省了移动大量元素所耗费的时间,然而这样做的缺点也是显而易见的,他失去了顺序表可以随极存取的优点。以下是对链表的一些简单描述。
首先定义一个结构:
struct person{
char name[20];
struct person *name;
};
我们可以看到,在这个结构中包含两个项目,分别是一个定义为char类型的数组和一个指针,这便是构成链表的元素——节点的基本构成。从这个定义可以知道,一个节点是由数据和指针两部分组成的,我们把存储数据的部分称为数据域,相应的把存储指针的部分称为指针域。每一个节点的指针都指向下一个节点,而最后一个节点指向NULL。至于第一个节点,我们在他之前定义了一个头节点,头节点的指针指向第一个节点,而头节点的数据域则不存放任何内容。当链表为空时,把头节点直接指向NULL。以上就是对一个链表所做的做简单的一个最简单的描述,接下来是对节点的一些操作。
我们需要做一些准备工作,除了必须定义一个用于构成链表的结构,声明一个头指针也是必不可少的。在使用链表前,他是一个不包含任何节点的空表,所以有必要把头指针初始化为NULL,还需要定义一个类型为链表结构的指针,用于添加节点,当然有时也许会需要多个这样的指针。这一切的具体实现如下:
struct person {
char name[20];
struct person *next;
};
struct person *new;
struct person *head;
head=NULL;
当一切准备工作就绪后,我们就可以对链表进行操作了。
*将节点加入到链表的开头
如果头指针为NULL,则说明链表之前是一个空表,新增加的节点是链表中的唯一节点。这时我们所要做的是让头指针指向新节点,而新节点的指针则指向NULL。或者链表之前不为空表,插入新节点的时候只要把新节点的指针指向原来的第一个节点就可以。无论那一种,他们都有几条共同的特性:
1.用malloc分配空间;
2.将新节点的next的指针设置为头指针的值;
3.让头指针指向新接点。
具体实现如下:
new=(person*)malloc(sizeof(struct person));
new->next=head;
head=new;
*将节点加入到链表末尾
将节点加入链表末尾,应从头指针开始往下找,直到最后一个节点,遍历整个链表。
1.分配空间;
2.最后一个节点的next指针指向新节点;
3.将新节点的next设置为NULL。
代码:
person *current;//定义当前指针
...
current=head;
while(current->next!=NULL)
current=current->next; //遍历整个链表节点
new=(person*)malloc(sizeof(struct person));
current->next=new;//new指针指向当前指针的next位置
new->next=NULL;
*将节点填加到链表中间
大多数情况下我们使用链表的时候都需要插入节点,步骤如下:
1.先确定链表要加入到哪个节点的后面。我们称其为标记节点(marker);
2.分配空间;
3.将标记节点的next指针指向新元素;
4.将新节点的next指针指向标记节点指向的节点。
代码:
person *marker;
...
new=(person)malloc(sizeof(struct person)
new->next=marker->next;
marker->next=new;
以上便是单链表的定义以及一些基本操作,通过单链表可以完成一些实际工作,比如字符排序。后面还有涉及到删除节点的内容,今天不做讨论。熟悉节点的基本操作对于深入链表来说是必不可少的,而深入的学习链表对于数据结构的入门帮助很大。数据结构是一门让人初学起来很摸不到头脑、甚至于不知道它到底能做什么的学科,泛泛的读书显然有可能越读越晕,找一个好的切入点进行深入,一段时间后会真正体会到数据结构的精髓的。想学好程序,数据结构是门不容跳过的学科,掌握扎实了今后受用无穷。