您的位置:首页 > 理论基础 > 数据结构算法

数据结构——线性表的顺序存储结构

2016-02-03 20:55 651 查看
最近寒假回来无聊想研究一下数据结构和算法。所以从头开始又开始看起了数据结构,现在才是刚起步所以只是浅显的实现了一下简单的数据结构,今天花了一天实现了线性表的顺序存储结构。首先了解一下什么是线性表:线性表就是零个或多个数据元素的有限序列。数据元素之间具有顺序关系。除了第一个数据元素和最后一个数据元素之外,其他数据元素都只有一个直接前驱和直接后继,而第一个元素只有直接后继没有直接前驱,最后一个元素只有直接前驱没有直接后继。而且线性表中的数据元素可以是简单类型的数据也可以是复杂的对象。线性表按存储方式分为两种,一种是顺序存储结构,另一种则是链式存储结构。所谓的顺序存储结构就是数据元素在内存中以连续的地址存储,学过c的都知道就像数组一样,内存分配一个连续的地址来存储数据元素。在这里链式存储结构暂时还未总结准备下一个阶段总结。

接下来就简单描述我实现的线性表的顺序存储结构的案例:

此案例是用来实现线性表的顺序存储结构

1、线性表的存储数据元素为学生对象,学生对象只有简单的学号和姓名(其中排序是以名字排的,为了实现理解我的名字格式是张3这样格式的,当然也可以改动的)

2、当线性表长度不够时不抛出异常而是动态添加线性表的长度

3、对线性表的的主要操作有:初始化、求长度、取值、设置值、定位、插入、删除、复制、合并、查找、排序、遍历

学生类作为存储的数据元素实现了Comparable接口,用于实现排序的:

package com.yc.entity;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
*
* 线性表的存储数据是一个学生对象
* @author WenQu
*/
public class Student implements Comparable<Student>{
//为了理解数据结构   数据元素的数据项只写了两个
private String sid;
private String sname;
public Student() {
}
public Student(String sid, String sname) {
this.sid = sid;
System.out.println("我的学号是:"+this.sid);
this.sname = sname;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((sid == null) ? 0 : sid.hashCode());
result = prime * result + ((sname == null) ? 0 : sname.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (sid == null) {
if (other.sid != null)
return false;
} else if (!sid.equals(other.sid))
return false;
if (sname == null) {
if (other.sname != null)
return false;
} else if (!sname.equals(other.sname))
return false;
return true;
}
//实现comparable接口来比较学生的大小
@Override
public int compareTo(Student student) {
//如果两个学生相等那么就直接不交换
if(this==student){
return 0;
}else{
//截取用正则表达式截取
Pattern pattern=Pattern.compile("[^0-9]"); //模式定义找到字符串中不是0-9中的
Matcher matcher=pattern.matcher(this.getSname());  //匹配模式中的字符串
int name=Integer.parseInt(matcher.replaceAll("") );  //替换匹配到的字符串
Matcher matcher2=pattern.matcher(student.getSname());
int sname=Integer.parseInt(matcher2.replaceAll("") );
if(name>sname){
return 1;
}else{
return -1;
}
}
}
}


线性表的实现类用来存储学生的:

package com.yc.bean;

import java.util.Arrays;
import javax.sound.midi.VoiceStatus;
import com.yc.entity.Student;

//这是用来存储学生的一个线性表的顺序存储结构
public class StudentList {
private Student[] studentList;  //线性表     表明创建的是一个线性表  数组的顺序是连续的
private static final int listLength=10;  //每次添加线性表的长度   静态常量节省空间
private int dateLength=0;  //记录线性表的实际存储数据长度
//线性表的实例化  也是其的初始化函数
public StudentList(){
}
//线性表的初始化
public void initList(){
studentList=new Student[listLength];
}
//获得线性表的存储数据长度
public int getDateLength(){
return dateLength;
}
//线性表获得链表
public Student[] getList(){
return Arrays.copyOf(this.studentList, dateLength);
}
//获得指定位置的数据元素
public Student getElement(int i){
//如果位置不对那么就输出
if(i<0||i>dateLength){
System.out.println("该位置为不合理位置!!!!");
return null;  //位置不存在返回空
}
return studentList[i-1];
}
//设定线性表的某个位置的值
public void setElement(int i,Student student){
if( !(student instanceof Student)||i<0||i>dateLength ){
//如果添加的元素不是学生类型那么就直接返回了
return;
}
//如果设置的条件是合理的那么就开始设置值
studentList[i-1]=student;
}
//插入一个元素  插在线性表的后面
public void insertInList(Student student){
//如果插入时长度不够那么就添加线性表的长度
if(dateLength>=studentList.length){
studentList=extendList();
}
//现在就可以动态的添加学生了
studentList[dateLength++]=student;
System.out.println("datelength的长度为:"+dateLength);
}
//按照位置插入
public void insertByI(int i,Student student){
//当插入的位置不存在时就直接返回
if(i<0||i>dateLength){
return;
}
//判断当前的数组长度是否已经满了  如果已经满了那么就先扩展数组的长度在添加
if(dateLength==studentList.length){
//拓展吸线性表的长度
studentList=extendList();
}
//然后开始进行再指定位置插入元素   把指定位置后面的元素往后移动然后在插入数据
for(int j=dateLength-1;j>=i-1;j--){
studentList[j+1]=studentList[j];
}
//最后把要插入的插进去
studentList[i-1]=student;
dateLength++;
}
//删除线性表中的某个位置的元素
public void delElement(int i){
//当位置超过元素个数的时候直接跳过
if(i<0||i>dateLength){
return;
}
//如果位置合理那么就可以直接进行删除
for(int j=i;j<dateLength;j++){
studentList[j-1]=studentList[j];
}
dateLength--;
}
//复制数组
public Student[] copyList(Student[] src,Student[] dest){
if(dest==null){
dest=new Student[src.length];
}
System.arraycopy(src, 0, dest, 0, src.length);
return dest;
}
//合并两个线性表
public Student[] combineList(Student[] s1,Student[] s2){
if(s1==null&&s2==null){
return null;
}
int count=0,dis=0;
count+=s1==null?0:s1.length;
count+=s2==null?0:s1.length;
Student[] temp=new Student[count];
if(s1!=null){
//复制第一个
System.arraycopy(temp, dis, s1, 0, s1.length);
dis+=s1.length;
}
if(s2!=null){
//复制第二个
System.arraycopy(temp, dis, s2, 0, s2.length);
}
return temp;
}
//查找满足条件的数据元素  返回null则是没有返回对象则是找到的与模板元素相等的
public Student searchElement(Student student){
for(int i=0;i<studentList.length;i++){
if(student==studentList[i]){
return studentList[i];
}
}
return null;
}
//排序  按照关键字的递减排序  使用的是冒泡排序
public void sortBySid(){
Student temp=null;
for(int i=0;i<dateLength-1;i++){
for(int j=0;j<dateLength-i-1;j++){
if(studentList[j].compareTo(studentList[j+1])<0){
//如果字符串比后面的小那么就交换
System.out.println("我是排序的"+studentList[j].getSname()+"和这个交换"+studentList[j+1].getSname());
temp=studentList[j+1];
studentList[j+1]=studentList[j];
studentList[j]=temp;
}
}
}
}
//遍历学生线性表
public void traverseList(){
for(int i=0;i<dateLength;i++){
System.out.println("姓名是:"+studentList[i].getSname()+",学号是:"+studentList[i].getSid());
}
}
//扩展数组的方法
public Student[] extendList(){
Student[] temp=new Student[studentList.length+listLength];
//然后将原来的数据复制到新的数组里面
System.arraycopy(studentList, 0, temp, 0, studentList.length);
//然后让原来的数组继续指向新的数组那么新数组的长度就变长了   实现了动态的添加长度
return temp;
}
}


总结:

1、在实现线性表的存储结构在排序的时候有一个问题想了很久,按姓名降序排序时为什么张90的排在张100的前面?

关于这个问题我总结了一下:在java中String的compareTo(String compareString)方法是将原字符串和参数字符串转换为ASCII码值进行比较的。而张90和张100字符串,字符串9的ASCII码值大于1的ASCII码值所有有张90>张100。所以才会是张90排在张100的前面。

2、那么如何实现字符串和数字的混合排序呢?例如张90和张100,在我写的线性表中姓是不重要的排序取决于后面的数字,可是姓也不排除有复姓,所以说白了就是要取出姓名中的中文或者说只需要取得姓名中的数字进行排序即可。后来想到了这样的解决办法。主要是用正则表达式来匹配。非数字的字符串替换为空剩下的数字字符串强制转换为整型即可。在java中则是这样实现的:

Pattern pattern=Pattern.compile("[^0-9]"); //模式定义 找到字符串中不是0-9中的

Matcher matcher=pattern.matcher(this.getSname()); //在给定的姓名字符串中匹配模式中的字符串

int name=Integer.parseInt(matcher.replaceAll("") ); //替换匹配到的字符串
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: