1. 数据结构


数据结构是计算机存储、组织数据的方式。常见的数据结构分类方式如下图:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#

常用的线性结构有:线性表,栈,队列,循环队列

线性表:是在内存中数据的一种组织、存储的方式。

                线性表顺序存储结构:用数组(连续存放的)来存储的线性表就是顺序表;

                线性表链式存储结构:  存储在链表上:单链表,双链表,循环链表.


栈和队列:只是属于逻辑上的概念,实际中不存在,仅仅是一种思想,一种理念;

                   栈和队列的实现可以用顺序存储结构或链式存储结构.


总结:顺序表 线性表 数组的区别 (你被这几个概念混淆,是因为你没搞懂数据结构里的逻辑结构和物理存储结构。)


a)数组就是相同数据类型的元素按一定顺序排列的集合。

一句话:就是物理上存储在一组联系的地址上。也称为数据结构中的物理结构。


b)线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。

一句话:线性表是数据结构中的逻辑结构。可以存储在数组上,也可以存储在链表上。


c)线性表的结点按逻辑次序依次存放在一组地址连续的存储单元里的方法。用顺序存储方法存储的线性表简称为顺序表。

一句话:用数组来存储的线性表就是顺序表。






1. 顺序表

顺序表将元素一个接一个的存入一组连续的存储单元中,在内存物理上是连续的。如下图:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_02

顺序表存储密度较大,节省空间;但需要事先确定容量,在时间性能方面,读运算较快,时间复杂度为O(1);查找运算为O(n/2),和链表同样;插入运算和删除运算如果要操作中间一个元素,比如3,那么就需要把3后面的元素全部进行移动,因此时间复杂度相对链表要大一些,插入时间复杂度最好为O(0)或最坏为O(n);删除时间复杂度为O([n-1]/2);


2. 链表

链表拥有很多结点,每个结点前半部分是数据域,后半部分是指针域,指针域指针指向下一个结点链表可分为单链表、循环链表和双链表。

单链表:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_03

从上图可以看出,单链表的上一个结点指针指向下一个结点,最后一个结点的指针域为null。

结点的删除

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_04

删除一个结点,如删除上图中q结点,只需将p结点中的指针域指向a3,然后将a2释放掉(free)即可。

结点的插入:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_05

插入一个结点,如插入上图中s结点,首先将s的指针域指向a2(也就是把s的next赋值为p的next),然后将p结点的指针域指向x即可(p的next指向x)。

循环链表

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_06

循环链表与单链表唯一不同之处是,循环链表的最后一个结点指针不为空,而是指向头结点。结点的插入和删除和单链表非常相似,就不再示范了。

双链表

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_07

双链表拥有一前一后两个指针域,从两个不同的方向把链表连接起来,如此一来,从两个不同的方向形成了两条链,因此成为双链表。因此,双链表的灵活度要大于单链表。

结点的删除:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_08

双链表的操作比单链表要稍显复杂(按照单链表思路来做其实也不难),如上图,要删除p节点,首先需要将a1的后驱指向a3,然后将a3的前驱指向a1,最后将p节点释放掉即可。

结点的插入:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_09

如上图,插入q结点,首先要按照方向,将步骤拆分,首先将q节点的前驱指向p结点后驱,紧接着将x后驱指向a2;然后按照顺序完成图中所示的3、4步即可。(@llhhyy1989  @voteforvip @wanghuan203 位童鞋的指正,发现此处有误,正确插入方法可查看评论,为保留错误原文不做改动!不懂具体插入过程可移步:百度知道

从空间性能来看,链表的存储密度要差一些,但在容量分配上更灵活一些。从时间性能来看,查找运算与顺序存储相同,插入运算和删除运算的时间复杂度为O(1),要更优于顺序存储,但读运算则弱一些,为O([n+1]/2),最好为1,最坏为n。

3. 栈

上面提到栈属于一个逻辑概念,栈的实现可以用顺序也可以用链式。它遵循先进后出原则,如下图:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_10

4. 队列

队列遵循先进先出的原则,如下图:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_11


5. 队列还有一种形式为循环队列,如下图:

3. C#数据结构与算法 -- 线性结构(线性表,栈,队列,循环队列) _c#_12

循环队列有两个指针,头指针head和尾指针tail,尾指针一般指向的不是队尾元素实际地址,而是指向实际地址的下一个空地址,因此,循环队列一般牺牲最后一个空间,用来计算该队列是否满了,判断方式是tail+1 = head,既该队列已满。


参考:
http://blog.csdn.net/bjyfb/article/details/7513505 

http://www.doc88.com/p-174473556475.html

 http://blog.csdn.net/foreverhuylee/article/details/37813053