`
daideshun
  • 浏览: 6530 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

习数组、队列、链表之所感

阅读更多
[size=xx-large][/size] 1.首先来谈谈数据在计算机世界的存储方式,数据元素在计算机中有两种不同的表示方法;一种是顺序的、一种是非顺序的。并由此得到两种不同的存储方式;既顺序存储结构、链式存储结构。

   顺序存储结构主要是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系,典型的数据结构就是经常用到的数组、线性表,其实线性表也是基于数组来实现的,
存储方式如下:

a表示数组的起始地址;
数组元素 a[0] a[1] a[2] … a[i] … a[n]
地 址     α    α+1 α+2 … α+i α+ n
二维数组也是类似如此: for example Array[m][n]; 其相当于由m个一维数组构成的数据存储,Array[i][0]指向每一个一维数组的起始地址;

[img]

[/img]

    2.有了数组这一种基本的数组结构作为基础,接下来,我们是否会进行一些扩展呢?
首先我们认识了数组是什么?它有什么优、缺、点,它适合什么样的场合?对我们编程更有利?

利用数组来组织数据结构
优点是:存储效率高,存取速度快。
缺点:
a. 对于数据元素个数动态增长的情况,由于数组个数不能自由扩充,一旦空间用完

就不能再向里加入新元素,否则,就会导致系统停工。

b. 插入、删除操作不方便,因为插入、删除操作会导致大量元素的移动,对于数组长度过大的话系统也可能没有那么多的连续的存储空间来开辟;


    首先我们一步一步的来,首先对于缺点a,我们是否可进行优化?使其能够实现动态添加的功能,首先我们要明确一点,要优化其本质的实现机制还是数组,只不过我们要实现自动扩容的功能;因此我们可以这样做:

给定一个数组的初始空间大小,这毫无疑问,数组吗,在定义时就要指定空间大小,其次当我们在往这个容器添加元素时,当空间不够时,我们将向系统申请一个空间更大的数组,申请完成后再进行拷贝赋值;

具体实现代码如下:

package java0418;
public class MyQueue<E> {
	int origin = 100;
	int increase = 10;
	Object Array[] = new Object[0];
	int len = 0;

	/*
	 * 无参构造
	 */
	public MyQueue() {
		Array = new Object[origin];
	}

	/*
	 * 用户自定义一个队列的初始长度
	 */
	public MyQueue(int len) {
		origin = len;
		Array = new Object[len];
	}
	/*
	 * 用户自定义容器的初始长度和增长幅度
	 */
	public MyQueue(int len, int inc) {
		origin = len;
		increase = inc;
		Array = new Object[len];
	}
	/*
	 * 添加元素的方法add();
	 */
	public void add(E data) {
		if (len >= Array.length) {
			Object Arc[] = new Object[Array.length + increase];
			System.arraycopy(Array, 0, Arc, 0, Array.length);
			Array = Arc;
		}
		Array[len++] = data;
	}

	public E getElement(int index) {
		E e = (E) Array[index];
		return e;
	}
}


   做到这一步,哎!长叹一口气!对于缺点a我们到是可以解决了,但是我们有没有发现每次在空间不够的时候我们都要重新拷贝一次(System.arraycopy(Array, 0, Arc, 0, Array.length);


  
  你写的这个程序是要给用户用的,当然咯你自己用的话也行,只不过这样就达不到我们写程序的最终目的了吧,乔布斯不是说过嘛:“活着就是要改变世界”,怎么改变啊?就是让更多的用户来用你的程序,给用户提供方便、友好、快捷的软件服务。所以我们不能把程序写死,要适当增加一些可供用户选择的服务,比如上面的小小列子吧,有的用户可能用的时候存放的数据并不是很多,它就可以指定小一点的初始长度和增长幅度,反之就可以设置大一点。


3.对于b来说,我们想怎么解决呢?想想我们上面讨论的都是应用了计算机的顺序存储结构,那对于这个问题我们是否可以应用计算机的随机链式存储来实现呢?答案是肯定的,不然要这个链式存储结构干嘛,于是我们就可以想到用链表来存放数据,
链表有两个域,一个是数据域,一个是指针域,数据域是存放你要存储的数据,指针域就是指向链表下一个节点的指针;

     指针作为维系结点的纽带,可以通过它实现链式存储。假设有五个学生某一门功课的成绩分别为A、B、C、D和E,这五个数据在内存中的存储单元地址分别为1248、1488、1366、1022和1520,其链表结构如图所示。
    [img]

[/img]

   链表有一个“头指针”变量,图中以 head表示,它存放一个地址,该地址指向链表中第一个结点,第一个结点又指向第二个结点……直到最后一个结点。该结点不再指向其他结点,它称为“表尾”,它的地址部分存放一个“NULL”(表示“空地址”),链表到此结束。链表中每个结点都包括两个部分:用户需要用的实际数据和下一个结点的地址。

然后我们就可以根据链表的特性构造一个链表类:

package com.hust.edu.dynProxy;

public class MyList<E> {
	private E data; // 数据域
	private MyList<E> next; // 指向下一个节点的指针域
	/*
	 * 相应的get和Set方法
	 */
	public E getData() {
		return data;
	}

	public void setData(E data) {
		this.data = data;
	}

	public MyList<E> getNext() {
		return next;
	}
	public void setNext(MyList<E> next) {
		this.next = next;
	}
}

再用一个类来进行创建一个链表:插入操作
[img]

[/img]
删除操作: 

[img]

[/img]
 
具体实现代码如下;

package com.hust.edu.dynProxy;

public class LinkList<E> {
	private MyList<E> root; // 链表的头结点
	private MyList<E> teml; // 链表的尾节点
	/*
	 * 对链表进行加入操作
	 */
	public void add(E data) {
		if (root == null) {
			root = new MyList<E>();
			teml = new MyList<E>();
			root.setData(data);
			teml = root;
		}
		else {
			MyList<E> tem = new MyList<E>();
			tem.setData(data);
			teml.setNext(tem);
			teml = tem;
		}
	}

	/*
	 * 对链表进行查找
	 */
	public E getElement(int index) {
		int i = 1;
		MyList<E> tem = new MyList<E>();
		tem = root;
		while (i < index && tem != null) {
			i++;
			tem = tem.getNext();
		}
		if (i == index && tem != null) {
			return (E) tem.getData();
		}
		return null;
	}

	/**
	 * 在指定的位置插入元素
	 */
	public void insert(E data, int index) {
		int i = 1;
		MyList<E> tem = new MyList<E>();
		tem = root;
		while (tem != null && i < index) {
			i++;
			tem = tem.getNext();
		}
		if (tem == null) {
			return;
		}
		else {
			MyList<E> p = new MyList<E>();
			p.setData(data);
			p.setNext(tem.getNext());
			tem.setNext(p);
		}
	}

	/**
	 * 删除第index个元素
	 */
	public void delete(int index) {
		int i = 1;
		MyList<E> tem = new MyList<E>();
		tem = root;
		if (index == 1) {
			root = root.getNext();
		}
		while (tem != null && i < index) {
			i++;
			tem = tem.getNext();
		}
		if (tem == null) {
			return;
		}
		else {
			MyList<E> q = new MyList<E>();
			q = tem.getNext();
			tem.setNext(q.getNext());
		}
	}

	/**
	 * 打印链表
	 */
	public void printLink() {
		MyList<E> tem = new MyList<E>();
		tem = root;
		while (tem != null) {
			System.out.println((E) tem.getData());
			tem = tem.getNext();
		}
	}

	public static void main(String[] args) {

		LinkList<String> lin = new LinkList<String>();
		lin.add("I ");
		lin.add("want ");
		lin.add("to ");
		lin.add("play ");
		lin.add("a ");
		lin.add("game... ");
		String s = lin.getElement(4);
		lin.delete(1);
		System.out.println(s);
		lin.printLink();
	}
}


运行结果如下:
play
want
to
play
a
game...


小结:
a.链表优于数组的:
  1.插入与删除的操作.如果数组的中间插入一个元素,那么这个元素后的所有元素的内存地址都要往后移动.删除的话同理.只有对数据的最后一个元素进行插入删除操作时,才比较快.链表只需要更改有必要更改的节点内的节点信息就够了.并不需要更改节点的内存地址.

  2.内存地址的利用率方面.不管你内存里还有多少空间,如果没办法一次性给出数组所需的要空间,那就会提示内存不足,磁盘空间整理的原因之一在这里.而链表可以是分散的空间地址.

  3.链表的扩展性比数组好.因为一个数组建立后所占用的空间大小就是固定的.如果满了就没法扩展.只能新建一个更大空间的数组.而链表不是固定的,可以很方便的扩展.

  b.链表的缺点是不利于查找,只能通过顺次指针访问,查询效率低;

   总之,当你碰到什么样的问题时,根据问题的性质选择恰当的数据结构进行优化你的程   序,
  各有利弊,避其锋芒 击其惰归。
  • 大小: 66.5 KB
  • 大小: 34.8 KB
  • 大小: 11.9 KB
  • 大小: 10.7 KB
分享到:
评论

相关推荐

    头歌 顺序表,链表,循环队列的基本操作和应用答案。

    这里我们讨论的是顺序表、链表以及循环队列,这些都是基本的数据结构,广泛应用于算法设计和程序实现中。 顺序表是一种线性数据结构,它在内存中按顺序连续存储元素。它的主要操作包括插入、删除和查找。在顺序表中...

    数据结构第三章栈和队列3习题.pdf

    队列的实现可以通过数组或链表来实现。在这里,我们使用数组来实现队列。 例如,在习题中,我们看到 front == rear表示队列为空,front+1 == rear表示队列只有一个元素。 3. 栈和队列的比较 栈和队列都是数据...

    数据结构队列习题.doc

    3. 链队列:链队列使用链表作为底层数据结构,通常包含头结点,方便处理队空情况。在链队列上进行出队操作,不会改变`front`指针,而是改变`front`指向的结点。链队列不会像顺序队列那样有“假溢出”,但在内存中...

    线性结构总结和习题( 数据结构 )

    队列是先进先出(FIFO)的数据结构,常用在任务调度、打印队列等,数组实现的循环队列和链表实现的队列都是常见方式。 带表头的单链表是链表的一种形式,表头节点不存储数据,方便插入和删除操作。在带表头的单链表...

    数据结构考研习题-第三章栈和队列.rar

    队列可以使用数组或链表实现,链式队列通常在动态扩展时更有效。 4. 循环队列和双端队列:循环队列解决了数组实现队列时的“假溢出”问题,而双端队列(Deque)允许在两端进行入队和出队操作,适用于实现滑动窗口...

    数据结构(C语言版) 清华大学出版社 第三章栈和队列 例题答案

    在C语言中,队列可以使用数组或者链表来实现。链队列通常由一系列节点组成,每个节点包含数据和指向下一个节点的指针。循环队列是队列的一种变体,通过巧妙地利用数组,使得队头和队尾可以在数组内的任何位置相遇,...

    java数据结构习题

    习题可能包括基于数组或链表的队列实现、优先队列(堆)或环形队列。 5. **散列表(哈希表)**:散列表通过哈希函数将键映射到数组的索引,提供快速的查找、插入和删除操作。习题可能涉及冲突解决策略(开放寻址法...

    数据结构习题与解析(c语言篇)

    《数据结构习题与解析(c语言篇)》可能包含了关于数组、链表、栈、队列、树、图、哈希表等各种数据结构的详细讲解和练习题目。 1. **数组**:数组是最基础的数据结构,它是一组相同类型元素的集合,可以通过索引来...

    常见数据结构习题详解与应用

    内容概要:本文涵盖了一系列的数据结构相关习题及其解答,旨在加深对数组、链表、栈、队列、二叉树、图的基础认识并提供实例实现,适合于备考面试者和技术精进的研发员使用。习题包括求解最大最小值数组元素查找、...

    《数据结构(C语言版)习题集》答案

    《数据结构(C语言版)习题集》是学习计算机科学与技术、软件工程等相关专业的重要教材之一,它涵盖了数组、链表、栈、队列、树、图等基础数据结构以及排序和查找算法等内容。本答案集将针对这些知识点进行详细解析。 ...

    数据结构习题与解析

    1. **线性结构**:包括数组、链表(单链表、双链表、循环链表)、栈和队列的定义、操作和应用实例。 2. **树结构**:如二叉树(二叉搜索树、完全二叉树、满二叉树)、平衡树(AVL树、红黑树)的概念、性质、插入和...

    数据结构课后习题答案

    这门课程通常会涉及到数组、链表、栈、队列、树、图等基本数据结构,以及排序和搜索算法等相关内容。在学习过程中,课后习题是巩固理论知识和提升实践能力的关键环节。以下是对"数据结构课后习题答案"中可能涉及的...

    栈和队列+串+数组和广义表+树和二叉树练习题.docx

    栈和队列+串+数组和广义表+树和二叉树练习题 本文档主要讲解了栈和队列、串、数组和广义表、树和二叉树等数据结构的概念和操作。通过对练习题的解答,帮助读者深入理解这些数据结构的特点和应用。 一、栈和队列 ...

    数据结构(C语言)的课后习题答案

    数据结构包括数组、链表、栈、队列、树、图等多种类型。在C语言中,这些数据结构可以通过结构体和指针来实现。例如,数组是固定大小的元素序列,可以实现基本的索引访问;链表则通过节点结构和指针实现动态存储,...

    数据结构习题与解析.pdf

    "数据结构习题与解析" 数据结构是计算机科学中的一门...数据结构习题与解析涵盖了数据结构的各个方面,包括栈和队列、数组和链表、树和图、算法分析等。mastering这些知识点可以帮助读者更好地理解和应用数据结构。

    数据结构(C语言版 第2版)课后习题答案 严蔚敏 编著

    栈和队列的实现可以通过数组或链表来实现。 第四章 树和图 树是一种非线性数据结构,通过节点和边来实现。树的基本操作包括遍历、插入、删除等等。图是一种复杂的数据结构,通过节点和边来实现。图的基本操作包括...

    计算机软件基础课后习题答案.pdf

    * 数组和链表:数组和链表是两种常见的线性表实现方式。 3. 栈、队列和数组:了解栈、队列和数组的概念和使用,包括栈的push和pop操作、队列的入队和出队操作等。 * 栈定义:栈是指后进先出(LIFO)的数据结构。...

    数据结构C语言版课件及习题

    C语言中,可以使用数组或链表实现队列。 树是一种非线性数据结构,包括二叉树、平衡树(如AVL树和红黑树)等。二叉树每个节点最多有两个子节点,而平衡树确保了查找、插入和删除操作的效率。 图由顶点和边构成,...

    (完整word版)数据结构C语言描述耿国华习题及答案.doc

    * 线性结构是指数据对象之间存在线性关系的数据结构,例如链表、队列、栈等。 树形结构 * 树形结构是指数据对象之间存在树形关系的数据结构,例如树形数组、树形链表等。 图状结构 * 图状结构是指数据对象之间...

    专升本数据结构历年真题及习题汇总

    线性表的实现可以使用数组或链表等数据结构。 栈和队列 栈和队列是数据结构中两种重要的数据结构。栈是一种后进先出的数据结构,元素之间的关系是线性的。队列是一种先进先出的数据结构,元素之间的关系也是一维的...

Global site tag (gtag.js) - Google Analytics