编程基础-数组和链表

数组和链表

  • 1.【数组】
    • 1.1 实现一个支持动态扩容的数组,支持增删改操作
    • 1.2 实现两个有序数组合并为一个有序数组
    • 1.3 学习哈希表思想,并完成leetcode上的两数之和(1)及Happy Number(202)!(要求全部用哈希思想实现!)(选做)(注意:在第四天会进行继续学习)
  • 2.【链表】
    • 2.1 实现单链表、循环链表、双向链表,支持增删操作
    • 2.2 实现单链表反转
    • 2.3 实现两个有序的链表合并为一个有序链表
    • 2.4 实现求链表的中间结点
  • 3.【对应的 LeetCode 练习题】
    • 3.1 Three Sum(求三数之和)
    • 3.2 Majority Element(求众数)
    • 3.3 Missing Positive(求缺失的第一个正数)[作为可选]
    • 3.4 Linked List Cycle I(环形链表)
    • 3.5 Merge k Sorted Lists(合并 k 个排序链表)

1.【数组】

1.1 实现一个支持动态扩容的数组,支持增删改操作

package SeqList;
public class SeqList<T> extends Object
{
	protected Object[] element;
	protected int n;
	public SeqList(int length)		//创建数组
	{
		this.element=new Object[length];
		this.n=0;
	}
	public SeqList()			//初始化数组
	{
		this(64);
	}
	public SeqList(T[] values)		//对数组进行赋值
	{
		this(values.length);
		for(int i=0;i<values.length;i++)
		{
			  this.element[i]= values[i];
		}
		this.n=element.length;
	}
	public boolean isEmpty()
	{
		return this.n==0;
	}
	public int size()		//返回数组长度
	{
		return this.n;
	}
	public T get(int i)		//返回第i个数组的值
	{
		if(i>=0&&i<this.n)
		{
			return (T)this.element[i];
		}
		return null;
	}
	public void set(int i,T x)	//更改个别第i个数组数据
	{
		if(x==null)
		{
			throw new NullPointerException("x==null");
		}
		if(i>0&&i<this.n)
		{
			this.element=(Object[]) x;
		}
		else
			throw new java.lang.IndexOutOfBoundsException(i+" ");
	}
	public String toString()  //遍历数组
	{
		String str=this.getClass().getName()+"(";
		if(this.n>0)
		{
			str+=this.element[0].toString();
		}
		for(int i=1;i<this.n;i++)
		{
			str+=","+this.element[i].toString();
		}
		return str+")";
	}
	public int insert(int i,T x)		//插入x作为第i个元素,x!==null,返回x序号

	{
		if(x==null)	
			throw new NullPointerException("x==null");	
		if(i<0)		
			i=0;	
		if(i>this.n)	
			i=this.n;		
		Object[] source=this.element;
		if(this.n==this.element.length)
		{
			this.element=new Object[source.length*2];
			for(int j=0;j<i;j++)		
				this.element[j]=source[j];		
		}
		for(int j=this.n-1;j>=i;j--)
		{
			this.element[j+1]=source[j];
		}
		this.element[i]=x;
		this.n++;
		return i;
	}
	public int insert(T x)				//插入x作为表尾,返回x序号
	{
		return this.insert(this.n,x);
	}
	public T remove(int i)				//删除第i个元素,0<=x
	{
		if(this.n>0&&i>=0&&i<this.n)
		{
			T old=(T)this.element[i];
			for(int j=i;j<this.n-1;j++)
			{
				this.element[j]=this.element[j+1];
			}
			this.element[this.n-1]=null;
			this.n--;
			return old;
		}
		return null;
	}
	public void clear()					//删除线性表所有元素
	{
		this.n=0;
	}
	public int search(T key)			//顺序查找首次出现的与key相等元素,返回元素序号i,查找不成功返回-1
	{
		for(int i=0;i<this.n;i++)
		{
			if(key.equals(this.element[i]))
				return i;
		}
		return -1;
	}
	public boolean contains(T key) {return this.search(key)!=-1;}//判断是否包含关键字为key元素
	public void removeAll(T key)		//删除所有关键字为key的元素;要求元素一次性移动到位
	{
		int m=0;
		for(int i=0;i<this.n;i++)		//顺序查找关键词key,并将相应的数字往前挪
		{
			if(!key.equals(this.element[i]))
			{
				this.element[m]=this.element[i];
				m++;
			}
		}
		this.n=m;
	}
	public void replaceFirst(T key ,T x)	//将首次出现的关键字为key元素替换为x
	{
		int m=search(key);
		if(m!=-1)
			this.element[m]=x;
	}
	public void replaceAll(T key,T x)		//将所有的关键字为key元素替换成为x

	{
		for(int i=0;i<this.n;i++)
		{
			if(this.element[i].equals(key))
			{
				this.element[i]=x;
			}
		}
	}
	public int searchLast(T key)			//顺序查询最后出现的关键词为key元素

	{
		for(int i=this.n-1;i>=0;i--)
		{
			if(this.element[i].equals(key))
			return i;
		}
		return -1;

	}
	public void removeLast(T key)			//删除最后出现的关键词为key元素
	{
		for(int i=this.n-1;i>=0;i--)
		{
			if(this.element[i].equals(key))
			{
				remove(i);
				i=-1;
			}
		}
	}
	public void replaceLast(T key,T x)		//顺序查找最后出现的关键词元素替换为x
	{
		int m=searchLast(key);
		if(m!=-1)	
			this.element[m]=x;		
	}
	public static void main(String[] args) {
		String[] values= {"A","B","D","C","D","D","E"};
		SeqList<String> lista=new SeqList<String>(values);
		System.out.println(lista.toString());
		lista.replaceFirst("D", "ZZ");
		System.out.println("将第一个出现的D改为ZZ:\n"+lista.toString());
	}
}

1.2 实现两个有序数组合并为一个有序数组

1.3 学习哈希表思想,并完成leetcode上的两数之和(1)及Happy Number(202)!(要求全部用哈希思想实现!)(选做)(注意:在第四天会进行继续学习)

2.【链表】

2.1 实现单链表、循环链表、双向链表,支持增删操作

Node类

package 单链表;
public class Node<T> {
	public T data;
	public Node<T> next;
	public Node(T data,Node <T> next)
	{
		this.data=data;
		this.next=next;
	}
	public Node()
	{
		this(null,null);
	}
	public String toString()
	{
		return this.data.toString();
	}
	public void print(Node<T> head)
	{
		Node<T> p=head;
		while(p!=null)
		{
			System.out.print(p.data.toString()+" ");
			p=p.next;
		}
	}
}

单链表类

package 单链表;

public class SinglyList<T> {
	public Node<T> head;					//头指针
	public SinglyList()						//构造空单链表
	{
		this.head=new Node<T>();
	}
	public SinglyList(T[] values)			//利用数组进行赋值
	{
		this();
		Node<T> rear=this.head;
		for(int i=0;i<values.length;i++)
		{
			rear.next=new Node<T>(values[i],null);
			rear=rear.next;
		}
	}
	public SinglyList(SinglyList<T> list)			//深拷贝构造函数
	{
		this();
		Node<T> rear=this.head;
		Node<T> rear1=list.head;
		for(int i=0;rear1.next!=null;i++)
		{
			rear.next=new Node<T>(rear1.data,null);
			rear=rear.next;
			rear1=rear1.next;
		}
	}
	public boolean isEmpty()				//判断是否为空单链表
	{
		return this.head.next==null;
	}
	public T get(int i)						//返回第i个元素,若越界,则为null
	{	
		Node<T> p=this.head.next;
		for(int j=0;p!=null&&j<i;j++)
		{
			p=p.next;
		}
		return (i>=0&&p!=null)?p.data:null;
	}
	public void set(int i,T x)						//设置第i个元素为x,0<=i<表长度,x!=null
	{	
		if(x!=null)
		{
			Node<T> p=this.head.next;
			for(int j=0;p!=null&&j<i;j++)
			{
				p=p.next;
			}
			p.data=x;
		}
		else 
			System.out.println(x+"无法插入!");
	}
	public int size()								//返回单链表长度,O(n)
	{
		Node <T> p=this.head.next;
		int i=0;
		while(p!=null)
		{
			i++;
			p=p.next;
		}
		return i;
	}
	public String toString()					//遍历单链表
	{
		String str=this.getClass().getName()+"(";
		for(Node<T> p=this.head.next;p!=null;p=p.next)
		{
			str+=p.data.toString();
			if(p.next!=null)			
				str+=",";		
		}
		return str+")";
	}
	public Node<T> insert(int i,T x)				//插入
	{
		if(x==null)		
			throw new NullPointerException("x==null");	
		Node<T> front=this.head;
		for(int j=0;front.next!=null&&j<i;j++)		
			front=front.next;		
		front.next=new Node<T>(x,front.next);
		return front.next;
	}
	public Node<T> insert(T x)				//在单链表最后添加对象x
	{
		return insert(Integer.MAX_VALUE,x);
	}
	public T remove(int i)					//删除第i个元素,0
	{
		Node<T> front=this.head;
		for(int j=0;front.next!=null&&j<i;j++)
		{
			front=front.next;
		}
		if(i>=0&&front.next!=null)
		{
			T old=front.next.data;
			front.next=front.next.next;
			return old;
		}
		return null;
	}
	public void clear()						//删除链表所有元素
	{
		this.head.next=null;
	}
	public Node<T> search(T key)			//查找返回首个与key相等元素结点,查找不成功返回null
	{
		Node<T> p=this.head.next;
		while(p!=null)
		{
			if(p.data==key)
				return p;
		}
		return null;
		
	}
	public boolean contains(T key)			//判断是否包含关键字为key元素
	{
		Node<T> p=search(key);
		return p!=null;
	}
	public T remove(T key)					//删除首个与key相等的元素,返回被删除元素
	{
		Node<T> p=this.head.next;
		int i=0;
		while(p!=null)
		{
			if(p.data==key)
				return remove(i);
			p=p.next;
			i++;
		}
		return null;
	}
	public double averageExceptMaxMin(SinglyList<Integer> list) 
	{
		double average=0;
		Node<Integer> p=list.head;
		Integer Max=list.head.next.data,Min=list.head.next.data;
		int i=0;
		for(;i==0||p.next!=null;i++)
		{ 
			average+=p.next.data;
			if(Max<=p.next.data)
				Max=p.next.data;
			if(Min>=p.next.data)
				Min=p.next.data;
			p=p.next;
		}
		System.out.println("Max="+Max);
		System.out.println("Min="+Min);
		average=(average-Max-Min)/(i-2);
		return average;
	}
	public static void main(String[] args)
	{
		Integer []a=new Integer[6];
		for(int i=0;i<a.length;i++)
			a[i]=i+1;
		SinglyList<Integer> lista=new SinglyList<Integer>(a);
		System.out.println(lista.toString());
		System.out.println("The averageExceptMaxMin is="+lista.averageExceptMaxMin(lista));
	}
}

循环单链表

package 单链表;
public class CirSinglyList<T> {
	public Node<T> head;					//头指针
	public CirSinglyList()						//构造空循环单链表
	{
		this.head=new Node<T>();
		this.head.next=this.head;
	}
	public CirSinglyList(T[] values)			//利用数组进行赋值
	{
		this();
		Node<T> rear=this.head;
		for(int i=0;i<values.length;i++)
		{
			rear.next=new Node<T>(values[i],null);
			rear=rear.next;
		}
		rear.next=this.head;
	}
	public boolean isEmpty()				//判断是否为空循环单链表
	{
		return this.head.next==this.head;
	}
	public T get(int i)						//返回第i个元素,若越界,则为null
	{	
		Node<T> p=this.head.next;
		for(int j=0;p!=this.head&&j<i;j++)
		{
			p=p.next;
		}
		return (i>=0&&p!=this.head)?p.data:null;
	}
	public void set(int i,T x)						//设置第i个元素为x,0<=i<表长度,x!=null
	{	
		if(x!=null)
		{
			Node<T> p=this.head.next;
			for(int j=0;p!=null&&j<i;j++)
			{
				p=p.next;
			}
			p.data=x;
		}
		else 
			System.out.println(x+"无法插入!");
	}
	public String toString()								//遍历循环双链表
	{
		String str=this.getClass().getName()+"(";
		for(Node<T> p=this.head.next;p!=this.head;p=p.next)
		{
			str+=p.data.toString();
			if(p.next!=this.head)		
				str+=",";		
		}
		return str+")";
	}
	public static void main(String[] args) {
		String[] str= {"A","B","C","D","E"};
		CirSinglyList<String> lista=new CirSinglyList<String>(str);
		System.out.println(lista.toString());
		System.out.println(lista.isEmpty());
		System.out.println(lista.get(2));
		lista.set(2, "X");
		System.out.println(lista.toString());
	}
}

双向单链表节点

package 双链表;
public class DoubleNode<T> {
	public T data;
	public DoubleNode<T> prev,next;
	public DoubleNode() 				//构造空结点的构造方法
	{
		this(null,null,null);
	}
	public DoubleNode(T data,DoubleNode<T> prev,DoubleNode<T> next)		//构造双链表节点 
	{
		this.data=data;
		this.prev=prev;
		this.next=next;
	}
	public DoubleNode(T data)
	{
		this(data,null,null);
	}
	public String toString()
	{
		return this.data.toString();
	}
}

双向单链表

package 双链表;
public class DoubleList<T> {
	public DoubleNode<T> head;
	public DoubleList()										//空双链表
	{
		this.head=new DoubleNode<T>();
	}
	public DoubleList(T[] values)							//构造双链表
	{
		this();
		DoubleNode<T> rear=this.head;
		for(int i=0;i<values.length;i++)
		{
			rear.next=new DoubleNode<T>(values[i],rear,null);
			rear=rear.next;
		}
	}
	public int size()										//返回双链表长度
	{
		DoubleNode<T> p=this.head;
		int i=0;
		for(;p.next!=null;i++)
		{
			p=p.next;
		}
		return i;
	}
	public boolean isEmpty()
	{
		return this.head.next!=null;
	}
	public String toPreviousString() 								//返回所有元素的描述字符串
	{
		String str=this.getClass().getName()+"(";
		for(DoubleNode<T> p=this.head.next;p!=null;p=p.next)
		{
			str+=p.data.toString();
			if(p.next!=null)		
				str+=",";		
		}
		return str+")";
	}
	public DoubleNode<T> insert(int i,T x)						//在第i个位置上插入数据x
	{
		if(x==null)		
			throw new NullPointerException("x==null");		
		if(i<0||i>this.size())	
			throw new NullPointerException(i+"超出双链表长度!");	
		DoubleNode<T> front=this.head;
		for(int j=0;front.next!=null&&j<i;j++)
		{
			front=front.next;
		}
		DoubleNode<T> p=new DoubleNode<T>(x,null,null);
		p.next=front.next;
		front.next=p;
		return front.next;
	}
	public DoubleNode<T> updata(int i,T x) 					//将第i个节点的data改为x
	{
		if(x==null)		
			throw new NullPointerException("x==null");		
		if(i<0||i>this.size())
			throw new NullPointerException(i+"超出双链表长度!");
		DoubleNode<T> front=this.head;
		for(int j=0;front.next!=null&&j<i;j++)
		{
			front=front.next;
		}
		front.next.data=x;
		return front.next;
	}
	public DoubleNode<T> insert(DoubleNode<T> p,T x)						//在p节点后插入节点q
	{
		DoubleNode<T> q=new DoubleNode<T>(x,p,p.next);
		p.next=q;
		p.next.prev=q;
		return q;
	}
	public DoubleNode<T> insert(T x,DoubleNode<T> p)						//在p节点前插入节点q
	{
		DoubleNode<T> q=new DoubleNode<T>(x,p.next,p);
		p.prev.next=q;
		p.prev=q;
		return q;
	}
	public DoubleNode<T> remove(int i)										//删除第i个节点,并返回被删除的节点
	{
		if(i<0||i>this.size())		
			throw new NullPointerException(i+"超出双链表长度!");		
		DoubleNode<T> front=this.head;
		for(int j=0;front.next!=null&&j<i;j++)
		{
			front=front.next;
		}
		DoubleNode<T> p=new DoubleNode<T>(front.next.data,null,null);
		front.next=front.next.next;
		front.prev=front;
		return p;
	}
	public DoubleNode<T> search(CirDoublyList<T> pattern)     	//查找首个与pattern匹配的子表
	{
		DoubleNode<T> p=this.head;
		return p;
	}
	public static void main(String[] args)
	{	
		String[] values= {"A","B","C","D","E"};
		DoubleList<String> lista=new DoubleList<String>(values);
		System.out.println(lista.toString()+"该双链表的长度为:"+lista.size());
		int i=1;
		System.out.println("删除第"+i+"个节点,该节点为"+lista.remove(i));
		System.out.println(lista.toString()+"该双链表的长度为:"+lista.size());
		System.out.println("修改第"+i+"个节点,该节点为"+lista.updata(i,"Z"));
		System.out.println(lista.toString()+"该双链表的长度为:"+lista.size());
	}
}

2.2 实现单链表反转

public void reverse(SinglyList<T> list)
	{
		 if (list.head == null || list.head.next== null)
	            return ;      
		Node<T> p=list.head;
		Node<T> prev=null;
		Node<T> n=null;
		while(p!=null)
		{
			n=p.next;
			p.next=prev;
			prev=p;
			p=n.next;
		}
	}

2.3 实现两个有序的链表合并为一个有序链表

2.4 实现求链表的中间结点

3.【对应的 LeetCode 练习题】

3.1 Three Sum(求三数之和)

英文版:https://leetcode.com/problems/3sum/
中文版:https://leetcode-cn.com/problems/3sum/

3.2 Majority Element(求众数)

英文版:https://leetcode.com/problems/majority-element/
中文版:https://leetcode-cn.com/problems/majority-element/

3.3 Missing Positive(求缺失的第一个正数)[作为可选]

英文版:https://leetcode.com/problems/first-missing-positive/
中文版:https://leetcode-cn.com/problems/first-missing-positive/

3.4 Linked List Cycle I(环形链表)

英文版:https://leetcode.com/problems/linked-list-cycle/
中文版:https://leetcode-cn.com/problems/linked-list-cycle/

3.5 Merge k Sorted Lists(合并 k 个排序链表)

英文版:https://leetcode.com/problems/merge-k-sorted-lists/
中文版:https://leetcode-cn.com/problems/merge-k-sorted-lists/

你可能感兴趣的:(编程基础)