最近学习了数据结构中的数组、链表和树,写得过程并没有出现什么很难解决的困难,但是总需要对自己的思路进行一次又一次的整理,并且在这个过程找的自己的错误以及对编码思路进行优化。在这里分享的主要是自己写得代码。
数组的性质:数组是定长的(在数组声明时,一定要写明数组的大小,否则会报错)
,有序的,数组中的每个元素都有一个唯一的索引位置。
数组的定义:类型[] 变量的名称=new 类型[大小]
e.g.
int[] arr=new int[]{1,2,3};
String[] arr2=new String[]{“a”, “abc”};
数组的实现:
这里只将数组类的定义写出来:
//输出的数组中的位置从一开始,但是储存的数组中位置从零开始。
例如12,23,34这个数组中,输出时显示的是1:12,2:23,3:34,但是在计算机中储存的时候,是0:12,1:23,2:34.
public class ArrayList implements List{
private Object[] oarr=new Object[0];
//添加一个元素到数组中 方法是:建立一个新的,比原数组的大小大一的数组,取代原数组。
public void add(Object obj) {
Object[] arr=new Object[oarr.length+1];
for(int i=0;i<oarr.length;i++){
arr[i]=oarr[i];
}
arr[arr.length-1]=obj;
oarr=arr;
}
//添加一组数据到数组中
public void add(Object[] objg){
int k=0;
Object[] arr=new Object[oarr.length+objg.length];
for(int i=0;i<oarr.length;i++){
arr[i]=oarr[i];
k=i;
}
//注意这里k的处理,是因为在测试时出现的不同的错误而进行的修改,虽然有点繁琐,但再没报错了,现在有更好的方法,努力寻找中...
if(k==0)k=-1;
System.out.println(k);
for(int i=0;i<objg.length;i++){
arr[k+i+1]=objg[i];
}
oarr=arr;
}
//指定一个位置,取出一个元素
public Object get(int index) {
if(index>=0&&index<oarr.length){
Object obj = oarr[index];
return obj;
}
return null;
}
//在指定位置中插入一个元素 方法是:建立一个新的,比原数组大小大一的数组,按顺序将元素安放在新的数组中
public void insert(int index, Object obj) {
Object[] arr=new Object[oarr.length+1];
for(int i=0;i<index;i++){
arr[i]=oarr[i];
}
arr[index]=obj;
for(int i=index;i<oarr.length;i++){
arr[i+1]=oarr[i];
}
oarr=arr;
}
//移除某元素,并将这元素输出 方法:建立新数组
public Object remove(int index) {
Object[] arr=new Object[oarr.length-1];
for(int i=0;i<index;i++){
arr[i]=oarr[i];
}
Object obj=oarr[index];
for(int i=index+1;i<oarr.length;i++){
arr[i-1]=oarr[i];
}
oarr=arr;
return obj;
}
//取得数组的大小
public int size() {
return oarr.length;
}
//给定一个确切的值,并输出其位置 假设数组中的数都不相同。若果该数不在数组内,则输出-1;
public int find(Object obj){
int target=-1;
for(int i=0;i<oarr.length;i++){
if(oarr[i].equals(obj)){
target=i+1;
}
}
return target;
}
//选出顺序表中的最小值
public int min(){
Integer min=(Integer)oarr[0];
for(int i=1;i<oarr.length;i++){
if(min>(Integer)oarr[i]){
min=(Integer)oarr[i];
}
}
return min;
}
//将数组输出
public void paint(){
for(int i=1;i<=oarr.length;i++){
System.out.print(i+":"+(Integer)oarr[i-1]+" ");
//想在输出了五个数之后转行 实现的方法:1.增加一个计数器 2.利用i,一旦i为4的倍数,则转行
if(i%4==0)System.out.println();
}
if(oarr.length%4!=0)
System.out.println();
}
}
数组队列的应用例子:
五子棋中棋子摆放位置的记录。
在五子棋的鼠标监听器中
public class ChessAction implements MouseListener{
Graphics gp;
Boolean isBlack=true;
int x1,y1,count=0;
//定义一个数组来保存信息!
Shape[] arrShapes=new Shape[100];
public ChessAction(Graphics gp){
this.gp=gp;
}
public void mouseClicked(MouseEvent e) {
ChessSpot cs=new ChessSpot();
cs.setX1(e.getX());
cs.setY1(e.getY());
if(isBlack){
gp.setColor(Color.black);
cs.setColor(Color.black);
isBlack=false;
}else{
gp.setColor(Color.white);
cs.setColor(Color.white);
isBlack=true;
}
//利用数组来保存五子棋的坐标信息
arrShapes[count++]=cs;
gp.fillOval(e.getX()-20,e.getY()-20,40,40);
}
}
链表:
链表和数组储存最大的一个区别就是,链表节点中除了数据,还包含了下一个节点的位置。这使得我们对链表上的数据查找这个过程方便很多。
链表节点的定义:
public class LinkNode {
public Object data;
public LinkNode next;}
创建链表:
public class CreatLink {
private LinkNode root;
private LinkNode tail;
private int lastpos;
private int count=0;
//添加一个元素
public void add(Object obj){
if(null==root){
root=new LinkNode();
root.data=obj;
tail=root;
}
else{
LinkNode nn=new LinkNode();
nn.data=obj;
tail.next=nn;
tail=nn;
}
count++;
}
//添加一系列节点
public void add(Object[] object){
if(null==root){
LinkNode[] nng=new LinkNode[object.length];
root=new LinkNode();
root.data=object[0];
nng[0]=root;
tail=root;
count++;
for(int i=1;i<object.length;i++){
nng[i]=new LinkNode();
nng[i].data=object[i];
nng[i-1].next=nng[i];
tail=nng[i];
count++;
}
}
}
//删除节点
public void remove(int index){
if(index>=1){
int i=0;
LinkNode m=root;
LinkNode target=root;
while(i<index-2){
target=m.next;
m=m.next;
i++;
}
target.next=target.next.next;
}
}
//取得位置为index上的节点数据
public Object get(int index){
if(index>=1){
int i=1;
LinkNode m=root;
LinkNode target=root;
while(i<index){
target=m.next;
m=m.next;
i++;
}
return target.data;
}
else return -1;
}
//取得链表长度
public int size(){
return count;
}
//输出链表
public void printLink(){
LinkNode tem=root;
int no=0;
while(tem!=null){
Object data=tem.data;
no++;
System.out.println("data"+no+" is:"+data);
tem=tem.next;
}
}
}
哈弗曼树:
哈弗曼树的节点定义:
public class HfmNode {
//节点的数据
int data;
//节点的编码
String code="";
//节点的左右孩子
HfmNode left,right;
}
public class HfmTree {
public static void main(String[] args){
int[] a={4,2,1};
HfmTree ht=new HfmTree();
ht.print(ht.creatTree(a));
}
建立哈弗曼树:
public HfmNode creatTree(int[] a){
//先将数组中的数据传进新建的节点
HfmNode[] nodes=new HfmNode[a.length];
for(int i=0;i<a.length;i++){
HfmNode node=new HfmNode();
node.data=a[i];
nodes[i]=node;
}
//循环建树
while(nodes.length>1){
//对节点数组进行排序
sort(nodes);
System.out.println("here");
//取出排序后的节点数组的前两个节点,即是数组中数值最小的两个
HfmNode n1=new HfmNode();
n1=nodes[0];
HfmNode n2=new HfmNode();
n2=nodes[1];
//为刚刚取出的两个节点建立父节点
HfmNode n3=new HfmNode();
n3.data=n1.data+n2.data;
n3.left=n1;
n3.right=n2;
System.out.println("n3="+n3.data);
//建立新的数组,这个数组里面取出了刚刚的最小的两个节点,并把新的父节点输入
HfmNode[] nodes2=new HfmNode[nodes.length-1];
for(int i=0;i<nodes2.length-1;i++){
nodes2[i]=nodes[i+2];
}
nodes2[nodes2.length-1]=n3;
//用新数组覆盖旧数组
nodes=nodes2;
}
HfmNode root=new HfmNode();
root=nodes[nodes.length-1];
return root;
}
//对节点数组进行排序
public void sort(HfmNode[] nodes){
for(int i=0;i<nodes.length;i++){
for(int j=i+1;j<nodes.length;j++){
if(nodes[i].data>nodes[j].data){
HfmNode tem=new HfmNode();
tem=nodes[i];
nodes[i]=nodes[j];
nodes[j]=tem;
}
}
}
//测试,将节点数组输出
for(int i=0;i<nodes.length;i++){
System.out.print(nodes[i].data+" ");
}
}
//对哈夫曼树进行编码,并将编码输出
public void print(HfmNode node){
if(node.left==null&&node.right==null){
System.out.println(node.data+"的哈弗曼编码为:"+node.code);
}
if(node.left!=null){
node.left.code=node.code+"0";
print(node.left);
}
if(node.right!=null){
node.right.code=node.code+"1";
print(node.right);
}
}
}
不管是创建数组、链表还是树,其实我觉得,最重要是我们的逻辑清晰,对数组、链表还有树的定义理解透彻,在编写代码是,难免会出现错误,我会努力尝试自己一个人找出错误。我觉得,自己找自己的错误是一个很好的学习机会,但是在找到错误之后,一定要总结一番。不然,即使改错了,但自己也不一定知道错了什么,最好就能找同学朋友讨论一番。
数组的性质:数组是定长的(在数组声明时,一定要写明数组的大小,否则会报错)
,有序的,数组中的每个元素都有一个唯一的索引位置。
数组的定义:类型[] 变量的名称=new 类型[大小]
e.g.
int[] arr=new int[]{1,2,3};
String[] arr2=new String[]{“a”, “abc”};
数组的实现:
这里只将数组类的定义写出来:
//输出的数组中的位置从一开始,但是储存的数组中位置从零开始。
例如12,23,34这个数组中,输出时显示的是1:12,2:23,3:34,但是在计算机中储存的时候,是0:12,1:23,2:34.
public class ArrayList implements List{
private Object[] oarr=new Object[0];
//添加一个元素到数组中 方法是:建立一个新的,比原数组的大小大一的数组,取代原数组。
public void add(Object obj) {
Object[] arr=new Object[oarr.length+1];
for(int i=0;i<oarr.length;i++){
arr[i]=oarr[i];
}
arr[arr.length-1]=obj;
oarr=arr;
}
//添加一组数据到数组中
public void add(Object[] objg){
int k=0;
Object[] arr=new Object[oarr.length+objg.length];
for(int i=0;i<oarr.length;i++){
arr[i]=oarr[i];
k=i;
}
//注意这里k的处理,是因为在测试时出现的不同的错误而进行的修改,虽然有点繁琐,但再没报错了,现在有更好的方法,努力寻找中...
if(k==0)k=-1;
System.out.println(k);
for(int i=0;i<objg.length;i++){
arr[k+i+1]=objg[i];
}
oarr=arr;
}
//指定一个位置,取出一个元素
public Object get(int index) {
if(index>=0&&index<oarr.length){
Object obj = oarr[index];
return obj;
}
return null;
}
//在指定位置中插入一个元素 方法是:建立一个新的,比原数组大小大一的数组,按顺序将元素安放在新的数组中
public void insert(int index, Object obj) {
Object[] arr=new Object[oarr.length+1];
for(int i=0;i<index;i++){
arr[i]=oarr[i];
}
arr[index]=obj;
for(int i=index;i<oarr.length;i++){
arr[i+1]=oarr[i];
}
oarr=arr;
}
//移除某元素,并将这元素输出 方法:建立新数组
public Object remove(int index) {
Object[] arr=new Object[oarr.length-1];
for(int i=0;i<index;i++){
arr[i]=oarr[i];
}
Object obj=oarr[index];
for(int i=index+1;i<oarr.length;i++){
arr[i-1]=oarr[i];
}
oarr=arr;
return obj;
}
//取得数组的大小
public int size() {
return oarr.length;
}
//给定一个确切的值,并输出其位置 假设数组中的数都不相同。若果该数不在数组内,则输出-1;
public int find(Object obj){
int target=-1;
for(int i=0;i<oarr.length;i++){
if(oarr[i].equals(obj)){
target=i+1;
}
}
return target;
}
//选出顺序表中的最小值
public int min(){
Integer min=(Integer)oarr[0];
for(int i=1;i<oarr.length;i++){
if(min>(Integer)oarr[i]){
min=(Integer)oarr[i];
}
}
return min;
}
//将数组输出
public void paint(){
for(int i=1;i<=oarr.length;i++){
System.out.print(i+":"+(Integer)oarr[i-1]+" ");
//想在输出了五个数之后转行 实现的方法:1.增加一个计数器 2.利用i,一旦i为4的倍数,则转行
if(i%4==0)System.out.println();
}
if(oarr.length%4!=0)
System.out.println();
}
}
数组队列的应用例子:
五子棋中棋子摆放位置的记录。
在五子棋的鼠标监听器中
public class ChessAction implements MouseListener{
Graphics gp;
Boolean isBlack=true;
int x1,y1,count=0;
//定义一个数组来保存信息!
Shape[] arrShapes=new Shape[100];
public ChessAction(Graphics gp){
this.gp=gp;
}
public void mouseClicked(MouseEvent e) {
ChessSpot cs=new ChessSpot();
cs.setX1(e.getX());
cs.setY1(e.getY());
if(isBlack){
gp.setColor(Color.black);
cs.setColor(Color.black);
isBlack=false;
}else{
gp.setColor(Color.white);
cs.setColor(Color.white);
isBlack=true;
}
//利用数组来保存五子棋的坐标信息
arrShapes[count++]=cs;
gp.fillOval(e.getX()-20,e.getY()-20,40,40);
}
}
链表:
链表和数组储存最大的一个区别就是,链表节点中除了数据,还包含了下一个节点的位置。这使得我们对链表上的数据查找这个过程方便很多。
链表节点的定义:
public class LinkNode {
public Object data;
public LinkNode next;}
创建链表:
public class CreatLink {
private LinkNode root;
private LinkNode tail;
private int lastpos;
private int count=0;
//添加一个元素
public void add(Object obj){
if(null==root){
root=new LinkNode();
root.data=obj;
tail=root;
}
else{
LinkNode nn=new LinkNode();
nn.data=obj;
tail.next=nn;
tail=nn;
}
count++;
}
//添加一系列节点
public void add(Object[] object){
if(null==root){
LinkNode[] nng=new LinkNode[object.length];
root=new LinkNode();
root.data=object[0];
nng[0]=root;
tail=root;
count++;
for(int i=1;i<object.length;i++){
nng[i]=new LinkNode();
nng[i].data=object[i];
nng[i-1].next=nng[i];
tail=nng[i];
count++;
}
}
}
//删除节点
public void remove(int index){
if(index>=1){
int i=0;
LinkNode m=root;
LinkNode target=root;
while(i<index-2){
target=m.next;
m=m.next;
i++;
}
target.next=target.next.next;
}
}
//取得位置为index上的节点数据
public Object get(int index){
if(index>=1){
int i=1;
LinkNode m=root;
LinkNode target=root;
while(i<index){
target=m.next;
m=m.next;
i++;
}
return target.data;
}
else return -1;
}
//取得链表长度
public int size(){
return count;
}
//输出链表
public void printLink(){
LinkNode tem=root;
int no=0;
while(tem!=null){
Object data=tem.data;
no++;
System.out.println("data"+no+" is:"+data);
tem=tem.next;
}
}
}
哈弗曼树:
哈弗曼树的节点定义:
public class HfmNode {
//节点的数据
int data;
//节点的编码
String code="";
//节点的左右孩子
HfmNode left,right;
}
public class HfmTree {
public static void main(String[] args){
int[] a={4,2,1};
HfmTree ht=new HfmTree();
ht.print(ht.creatTree(a));
}
建立哈弗曼树:
public HfmNode creatTree(int[] a){
//先将数组中的数据传进新建的节点
HfmNode[] nodes=new HfmNode[a.length];
for(int i=0;i<a.length;i++){
HfmNode node=new HfmNode();
node.data=a[i];
nodes[i]=node;
}
//循环建树
while(nodes.length>1){
//对节点数组进行排序
sort(nodes);
System.out.println("here");
//取出排序后的节点数组的前两个节点,即是数组中数值最小的两个
HfmNode n1=new HfmNode();
n1=nodes[0];
HfmNode n2=new HfmNode();
n2=nodes[1];
//为刚刚取出的两个节点建立父节点
HfmNode n3=new HfmNode();
n3.data=n1.data+n2.data;
n3.left=n1;
n3.right=n2;
System.out.println("n3="+n3.data);
//建立新的数组,这个数组里面取出了刚刚的最小的两个节点,并把新的父节点输入
HfmNode[] nodes2=new HfmNode[nodes.length-1];
for(int i=0;i<nodes2.length-1;i++){
nodes2[i]=nodes[i+2];
}
nodes2[nodes2.length-1]=n3;
//用新数组覆盖旧数组
nodes=nodes2;
}
HfmNode root=new HfmNode();
root=nodes[nodes.length-1];
return root;
}
//对节点数组进行排序
public void sort(HfmNode[] nodes){
for(int i=0;i<nodes.length;i++){
for(int j=i+1;j<nodes.length;j++){
if(nodes[i].data>nodes[j].data){
HfmNode tem=new HfmNode();
tem=nodes[i];
nodes[i]=nodes[j];
nodes[j]=tem;
}
}
}
//测试,将节点数组输出
for(int i=0;i<nodes.length;i++){
System.out.print(nodes[i].data+" ");
}
}
//对哈夫曼树进行编码,并将编码输出
public void print(HfmNode node){
if(node.left==null&&node.right==null){
System.out.println(node.data+"的哈弗曼编码为:"+node.code);
}
if(node.left!=null){
node.left.code=node.code+"0";
print(node.left);
}
if(node.right!=null){
node.right.code=node.code+"1";
print(node.right);
}
}
}
不管是创建数组、链表还是树,其实我觉得,最重要是我们的逻辑清晰,对数组、链表还有树的定义理解透彻,在编写代码是,难免会出现错误,我会努力尝试自己一个人找出错误。我觉得,自己找自己的错误是一个很好的学习机会,但是在找到错误之后,一定要总结一番。不然,即使改错了,但自己也不一定知道错了什么,最好就能找同学朋友讨论一番。