`
freewxy
  • 浏览: 342844 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

数组和链表的比较以及队列的两种方式实现

阅读更多

1、定义  

  数组又叫做顺序表顺序表是在内存中开辟一段连续的空间来存储数据数组可以处理一组数据类型相同的数据,但不允许动态定义数组的大小,即在使用数组之前必须确定数组的大小。而在实际应用中,用户使用数组之前有时无法准确确定数组的大小,只能将数组定义成足够大小,这样数组中有些空间可能不被使用,从而造成内存空间的浪费。

 链表是一种常见的数据组织形式,它采用动态分配内存的形式实现。链表是靠指针来连接多块不连续的的空间,在逻辑上形成一片连续的空间来存储数据需要时可以用new分配内存空间,不需要时用delete将已分配的空间释放,不会造成内存空间的浪费。

2、二者区分: 

 从逻辑结构来看

  A-1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。

  A-2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)

    B 从内存存储来看

  B-1. (静态)数组从栈中分配空间对于程序员方便快速,但是自由度小

  B-2. 链表从堆中分配空间自由度大但是申请管理比较麻烦.

       数组在内存中开辟连续的一块区域,如果一个数据要两个内存单元,一组5个数据10个单元就够了,无需标记其地址,因为数组定义时候标顶了第一个原始的地址,其他四个都知道了。

       链表可可以是连续的,也可以是不连续的,但一般都是不连续的,一链5个数据,如果每个数据本身用2个内存单元,那么10个单元是不够的,因为每个数据都要表示出下个数据在哪里,所以一个数据本身用2个单元,再用1个单元表示此链下一个数据在什么地址。

 C从访问顺序来看 

       数组中的数据在内存中的按顺序存储的,而链表是随机存储的!

  C-1.要访问数组中的元素可以按下标索引来访问,速度比较快,如果对他进行插入操作的话,就得移动很多元素,所以对数组进行插入操作效率很低!

  C-2.由于链表表是随机存储的,链表在插入,删除操作上有很高的效率(相对数组),如果要访问链表中的某个元素的话,那就得从链表的头逐个遍历,直到找到所需要的元素为止,所以链表的随机访问的效率就比数组要低

 

3、分别用数组和链表实现队列:

    3-1数组实现

public class Queue <E>{
    
	//每次放入队列的元素的个数
	private int initLen=0;
	//每次增长的队列空间的大小
	private int increaseLen=0;
	private Object[] src;
	//己放入对象的个数
	private int count=0;
	
	public Queue(int initLen,int increaseLen){
		this.initLen=initLen;
		this.increaseLen=increaseLen;
		src = new Object[initLen];
	}
	
	public Queue(int initLen){
		this(initLen,initLen/2);
	}
	
	public Queue(){
		this(20,10);
	}
	
	
	/**
	 * 在末尾向队列中增加一个字符串
	 * @param s:向队列中增加的字符串 
	 */
	public void add(E e){
		src[count]=e;
		count++;
		if(count>=initLen){
			//新建数组,是原数组长度的length+1
			Object[] temp=new Object[src.length +increaseLen];
			//将原数组中的复制到新数组中
			for(int i=0;i<count;i++)
			{
				temp[i]=src[i];
			}
			src=temp;	
		}
		
	}
	/**
	 * 在指定位置向队列中增加一个字符串s
	 * @param s 向队列中增加的字符串
	 * @param index 队列中指定的位置
	 */
	public  void add(E e,int index){
		if(count>=initLen){
			//新建数组,是原数组长度的length+increaseLen
			Object[] temp=new Object[src.length +increaseLen];
			//将原数组中的复制到新数组中
			for(int i=0;i<count;i++)
			{
				temp[i]=src[i];
			}
			//新数组赋值给原数组
			src=temp;	
		}
		//将原数组从index处的元素向后以一位
		for(int i=count;i>index;i--)
		{
			src[i]=src[i-1];
		}
		//将s添加到新数组中指定位置
		src[index]=e;
	
	}
	
	/**
	 * 得到队列中指定位置的字符串
	 * @param index 队列中指定的位置
	 * @return 返回指定位置的字符串
	 */
	public E get(int index){
		if(index>=0&&index<=count){
		   return (E)src[index];
		   }
		else return null;
	}
	
	/**
	 * 返回当前字符串的位置
	 * @param s当前字符串
	 * @return 当前字符串的位置
	 */
	public int getPos(E e){
		 int temp=-1;
		for(int i=0;i<count;i++){
			if(e.equals(src[i])){
				temp=i;
		        break;
			}
		
		}
		//System.out.println("位置是:"+temp);
		if(temp==-1)
		 System.out.println("队列中没有与  \""+e+"\" 匹配的字符串!");
		return temp;
	}
	
	/**
	 * 得到队列中字符串的长度即大小
	 * @return 返回的是字符串的大小
	 */
	public int size(){
		return count;
	}
	 
	/**
	 * 删除队列中指定位置的字符串
	 * @param index 要删除字符串的位置
	 * @return 返回锁删除的字符串
	 */
	public E delete(int index){
		//System.out.println("字符串的长度为"+src.length);
		//新建数组,是原数组长度的length+1
		Object[] temp=new Object[count-1];
		E e;
		//将原数组index前的元素复制到新数组中
		for(int i=0;i<index;i++)
		{
			temp[i]=src[i];
		}
		e=(E)src[index];
		//将原数组index后的元素复制到新数组中
		for(int i=index+1;i<count;i++)
		{
			temp[i-1]=src[i];
		}
		//新数组赋值给原数组
		src=temp;
		count--;
		//System.out.println("字符串的长度为"+src.length);
		return e;
	}
	
	/**
	 * 删除指定的字符串
	 * @param s要删除的字符串
	 * @return TRUE删除成功 FALSE删除失败
	 */
	public Boolean delete(E e){
		 int temp=-1;
			for(int i=0;i<count;i++){
				if(e.equals(src[i])){
					temp=1;
			        break;
				}
			}
			if(temp!=-1)return true;
			return false;
	}
	
	/**
	 * 替换队列中指定位置的字符串
	 * @param s新的字符串
	 * @param index要更新字符串的位置
	 * @return
	 */
	public Boolean replace(E e,int index){
        if(index>count){
        	System.out.println("长度超出!!");
        	return false;
        	}
		E temp;
		temp=(E)src[index];
		src[index]=e;
		e=temp;
		return true;
	}
	
}

  3-2链表实现

 

public class Node<E> {
	public E Elem;
	public Node<E> next;
	public Node(E elem){
		Elem=elem;
	}
	public String toString(){
		return Elem.toString();
	}
}

public class LinkQueueDemo <E>{
	    
    public Node head=null;
    public Node tail=null;
	/**
		* 在末尾向队列中增加一个节点
		* @param s:向队列中增加的字符串 
		*/
	public void add(E elem){
		if(head==null){
			head=new Node(elem);
            tail=head;
		}else{
			tail.next=new Node(elem);
            tail=tail.next;	   
		}
		//System.out.println("插入的Node是:"+elem);
	}
	
		/**
		 * 得到队列中指定位置的字符串
		 * @param index 队列中指定的位置
		 * @return 返回指定位置的字符串
		 */
		public Node get(int index){
		    Node temp=head;
		    int count=0;
		    if(index>this.size()){
		    	System.out.println("index is out of the size:"+this.size());
		    	return null;
		    }else if(temp==null){
		    	System.out.println("queue is empty;");
		    	return null;
		    }else{
		    	 while(count!=index){
		    		 count++;
		    		 temp=temp.next;
		    	 }
		         return  temp;
		     }
		     
		}
		
		/**
		 * 返回当前节点的位置
		 * @param s当前字符串
		 * @return 当前字符串的位置
		 */
		public int getPos(E e){
			Node temp=head;
			Node query_Node=new Node(e);
		    int count=0;
		   if(temp==null){
		    	System.out.println("queue is empty;");
		    	return -1;
		    }else{
		    	 while(temp.Elem!=query_Node.Elem&&temp.next!=null){
		    		 count++;
		    		 temp=temp.next;
		    	 }
		    	 if(temp.next==null){
		    		 System.out.println("there is no such Node");
		    		 return -1;
		    	 }
		    		
		         return count;
		     }
		}
		
		/**
		 * 得到队列中字符串的长度即大小
		 * @return 返回的是字符串的大小
		 */
		public int size(){
			int len=0;
			Node temp=head;
			if(head==null)
				return 0;
		    while(temp!=null){
		    	len++;
		    	temp=temp.next;
		    }
	         return len;
		}
		 
		/**
		 * 删除队列中指定位置的字符串
		 * @param index 要删除字符串的位置
		 * @return 返回锁删除的字符串
		 */
		public Node delete(int index){
			Node temp=head;
			Node pretem=temp;
		    int count=0;
		    if(index>this.size()){
		    	System.out.println("index is out of the size:"+this.size());
		    	return null;
		    }else if(temp==null){
		    	System.out.println("queue is empty;");
		    	return null;
		    }else{
		    	 while(count!=index){
		    		 count++;
		    		 pretem=temp;
		    		 temp=temp.next;
		    	 }
		         pretem.next=temp.next;
		     }
			return temp;
		}
		
		/**
		 * 删除队列中第一个Node
		 * @return 返回锁删除的node 
		 */
		public Node delete(){
			Node temp=head;
			if(temp==null){
				System.out.println("the queue is empty!");
				return null;
			}else{
			    if(head.next!=null){
			    	head=head.next;
			    }	
			    else{
			    	head=null;
			    }
			    return temp;
			}
		}
		
		/**
		 * 删除指定的字符串
		 * @param s要删除的字符串
		 * @return TRUE删除成功 FALSE删除失败
		 */
		public Boolean delete(E e){
			
				return false;
		}
		
		/**
		 * 替换队列中指定位置的字符串
		 * @param s新的字符串
		 * @param index要更新字符串的位置
		 * @return
		 */
		public Boolean update(E e,int index){
			Node temp=head;
		    int count=0;
		    if(index>this.size()){
		    	System.out.println("index is out of the size:"+this.size());
		    	return false;
		    }else if(temp==null){
		    	System.out.println("queue is empty;");
		    	return false;
		    }else{
		    	 while(count!=index){
		    		 count++;
		    		 temp=temp.next;
		    	 }
		         temp.Elem=e;
		     }
			return true;
		} 
		
		public void printQueue(){
			Node temp=head;
			int count=0;
			while(temp!=null){
				System.out.println(count+":"+temp+" ");
				temp=temp.next;
			    count++;
			}
		}
}

 

 

<!--EndFragment-->
分享到:
评论
2 楼 freewxy 2010-11-19  
引用
你的想法很好,可以让用户自己决定开辟多少空间,也可以由我们自己决定开辟多少空间,我就没想到(惭愧啊!~)。但是我很好奇,为什么你要加上第一个构造函数呢?如果用户输入的需要增加的空间过大,会很浪费资源的。那个要增长的空间长度可以由我们自己定啊!~(个人见解)

嗯,确实,这点我没有考虑到,这个内部定义会更好一些
1 楼 吸血鬼猎人 2010-11-19  
 public Queue(int initLen,int increaseLen){   
12.        this.initLen=initLen;   
13.        this.increaseLen=increaseLen;   
14.        src = new Object[initLen];   
15.    }   
16.       
17.    public Queue(int initLen){   
18.        this(initLen,initLen/2);   
19.    }   

       public Queue(){   
22.        this(20,10);   
23.    }   



你的想法很好,可以让用户自己决定开辟多少空间,也可以由我们自己决定开辟多少空间,我就没想到(惭愧啊!~)。但是我很好奇,为什么你要加上第一个构造函数呢?如果用户输入的需要增加的空间过大,会很浪费资源的。那个要增长的空间长度可以由我们自己定啊!~(个人见解)

相关推荐

    数组和链表实现队列

    本话题主要探讨了两种常用的数据结构——数组和链表——在实现队列这一线性数据结构时的应用。队列是一种先进先出(First In First Out, FIFO)的数据结构,它的主要操作包括入队(enqueue)、出队(dequeue)以及...

    python利用数组和链表实现栈和队列 数组和链表.pdf

    Python 实现栈和队列 栈和队列是两种常用的数据结构,在编程设计中广泛应用。...本文介绍了如何使用 Python 实现栈和队列,包括使用数组和链表两种方法。栈和队列是两种常用的数据结构,在编程设计中广泛应用。

    数组、链表、队列、栈的区别和联系 数组和链表.pdf

    队列和栈都是描述数据存取方式的概念,它们可以使用数组或链表实现。 队列是一种先进先出(First-In-First-Out,FIFO)的数据结构,元素的添加和删除都是从队列的两端进行的。队列可以使用数组或链表实现,数组实现...

    队列的链表与数组分别实现

    本篇文章将深入探讨如何用数组和链表两种数据结构来实现队列。 ### 数组实现队列 数组实现队列的优势在于访问速度快,因为数组是连续存储的,可以通过下标直接访问元素。但数组的大小是固定的,所以在创建时需要...

    C++循环队列模版(数组和链表两种实现方式都有)

    总结一下,C++中的循环队列可以通过数组和链表两种方式实现,每种实现都有其特点。数组实现访问速度快,但处理满队列和空队列需要特殊考虑;链表实现插入和删除操作灵活,但访问速度较慢。模板机制使得循环队列可以...

    数组、链表、堆栈和队列、线性表和顺序表 数组和链表.pdf

    数组、链表、堆栈和队列、线性表和顺序表 数组、链表、堆栈和队列是最基本的数据结构,任何程序都会涉及到其中的一种或多种。数据结构是指数据之间的相互关系,即组织形式,有逻辑结构和物理结构之分。逻辑结构有...

    数组和链表的对比分析 数组和链表.docx

    本篇文章主要探讨的是两种基本的数据结构——数组与链表。通过对比它们的特点、优缺点以及适用场景,帮助读者更好地理解何时选择哪种数据结构更为合适。 #### 数组与链表概述 **数组**是一种常见的数据结构,它是...

    数组和链表分别比较适合用于什么场景 数组和链表.pdf

    数组和链表是两种基本的数据结构,它们各自有其适用的场景和特点。在计算机科学中,选择合适的数据结构对于程序的效率和性能至关重要。 数组是一种线性数据结构,它在内存中以连续的方式存储元素。这意味着数组的...

    java双端队列的实现-Java实现自定义双端队列(链表和数组两种方式) 数组和链表.pdf

    在 Java 中,LinkedList 的内部使用双端链表队列原理实现,而 ArrayList 的内部使用双端数组队列原理实现。 Java 实现自定义双端队列可以通过链表和数组两种方式实现,双端队列可以充当单端队列,也可以用于充当栈...

    数组和链表(使用场景和反转链表) 数组和链表.pdf

    在计算机科学中,数组和链表是两种最为基本且广泛使用的数据结构,它们承载着计算机存储和处理数据的重任。尽管它们各自拥有不可替代的特性,但其适用场景和性能效率却大相径庭,因此在实际开发过程中,正确选择和...

    循环链表队列 循环数组队列的代码实现

    本文将深入探讨两种队列实现方式:循环链表队列和循环数组队列,并通过代码示例进行详细解析。 #### 循环链表队列 循环链表队列是一种使用链表实现的队列,其中最后一个节点的指针指向第一个节点,形成一个循环。...

    java数组和链表数据结构的区别 数组和链表.pdf

    在计算机科学中,数据结构是组织、存储和处理数据的方式,它们是算法设计的基础。...在实际编程中,Java提供了ArrayList和LinkedList两种内置的列表实现,分别基于数组和链表,可以根据需要选择使用。

    数组和链表的理解,及各自的优缺点 数组和链表.pdf

    在众多数据结构中,数组和链表是最为基础且常用的两种。它们在存储和处理数据方面呈现出不同的特点,各自拥有独特的优势和局限性,因此在不同的应用场景中扮演着至关重要的角色。下面将对数组和链表进行详细分析,并...

    c语言数组指定位置插入和删除-玩转C语言链表,单链表双向链表的建立遍历插入删除... 数组和链表.pdf

    本文主要讲解了C语言中数组和链表的概念及操作,包括数组指定位置插入和删除、链表的结构、静态链表和动态链表、单链表的建立和遍历、双向链表的概念、循环链表的概念等。同时也涉及到了链表的实战应用和拓展思维。 ...

    数据结构顺序表、链表和数组是逻辑结构还是物理(存储)结构? 数组和链表.pdf

    逻辑结构和物理结构是两种不同的概念,逻辑结构是对数据元素之间的关系的抽象描述,而物理结构是对数据元素在存储器中的存储方式的描述。两者都是数据结构的组成部分,但它们是不同的层次,逻辑结构是理论思想,而...

    java中链表和数组的区别? (1) 数组和链表.pdf

    在Java编程中,数据结构是基础,而数组和链表是两种常见的线性数据结构。它们各有特点,适用于不同的场景。下面将详细讨论这两种数据结构的区别。 首先,数组是一种静态分配内存的数据结构,其所有元素在内存中是...

    链表和数组的区别与作用应该知道吧 数组和链表.pdf

    数组和链表作为两种基础的数据结构,它们的特点和使用场景各不相同,深入了解它们的区别与作用对于编程人员至关重要。 数组是一种简单而又强大的数据结构,它在内存中占据一块连续的空间,以顺序的方式存储同一类型...

    循环数组实现队列

    队列有两种存储形式:链式和循环数组存储。 在哈工大软件设计代码中,队列的实现是使用循环数组存储结构的。该存储结构的实现是使用模板类的方式,定义了一个名为MyQueue的类,包含了队列的基本操作:入队、出队、...

    数组的扩容和链表结构.zip

    在Java编程语言中,数组和链表是两种基础且重要的数据结构。它们各自有独特的特点和使用场景,尤其是在处理大量数据时,理解它们的工作原理和性能特性至关重要。本压缩包文件"数组的扩容和链表结构.zip"包含了关于...

    学习电脑信息数组与链表的优缺点

    数组和链表是两种基本的数据结构,它们各自有其独特的优缺点,在不同的场景下有着不同的应用。 数组是一种静态数据结构,它在内存中占据连续的空间,这意味着数组的大小在创建时就已经固定,不能轻易地增加或减少。...

Global site tag (gtag.js) - Google Analytics