002.数据结构_线性结构

一、线性表:n个相同类型数据的有限序列(n>=0)。

    常用操作:增(尾部)、删、插、查、遍历、求表长、判断是否为空

    操作特点:可以在任意位置插入或删除一个元素。


二、顺序表:用顺序结构实现的线性表。

    Java类库中的顺序表:ArrayList

//StudIn类:定义顺序表中的数据元素
public class StudIn {
	private String name;
	private int id;
	private double score;
	public StudIn(String name,int id,double score){
		this.name=name;
		this.id=id;
		this.score=score;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public double getScore() {
		return score;
	}
	public void setScore(double score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "StudIn [姓名=" + name + ", 学号=" + id + ", 分数=" + score + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(score);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		StudIn other = (StudIn) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(score) != Double.doubleToLongBits(other.score))
			return false;
		return true;
	}
	
}
//StudOPeration接口:定义顺序表的数据操作
public interface StudOPeration {
	void add(StudIn node);//在尾部添加一个学生记录
	void listAll();//遍历学生记录
	void search(int index);//查询某个位置上学生的信息并输出
	int getCounts();//获取学生记录个数
	void delete(int index);//根据记录序号删除学生记录
	void delete(String name);//根据学生姓名删除学生信息
	void search(String name);//根据学生姓名查找学生信息
}
//ArrStudentl类:是一个顺序表,用来实现StudOPeration接口
public class ArrStudent implements StudOPeration{
//	StudIn[]stud=new StudIn[5];
	StudIn stud[];
	public ArrStudent(int size) {   //指定顺序表的容量
		// TODO Auto-generated constructor stub
		stud=new StudIn[size];
	}
	
	int cout=0;//记录计数器,记当前顺序表中 的记录个数
	
	@Override
	public void add(StudIn node) {  //添加纪录
		// TODO Auto-generated method stub
		int i=cout;
		stud[i]=node;
		cout++;
		if(cout==stud.length){
			System.out.println("存储空间已满");
		}
		
	}

	@Override
	public void listAll() {  //显示所有记录
		// TODO Auto-generated method stub
		try{for(int i=0;i<cout;i++){
			System.out.println(stud[i].getName()+"\t"+stud[i].getId()+"\t"+stud[i].getScore());
		}}catch(NullPointerException e){
			e.printStackTrace();
		}
	}

	@Override
	public void search(int index) {  //查询记录
		// TODO Auto-generated method stub
		if(index<=stud.length&&index>0){
			System.out.println("您查找的信息为:"+stud[index-1]);
		}else{
			System.out.println("输入序号无效");
		}	
	}

	@Override
	public int getCounts() {  //获取学生记录个数
		// TODO Auto-generated method stub
		return cout;
	}

	@Override
	public void delete(int index) {
		// TODO Auto-generated method stub
		cout=cout-1;
		stud=ArrStudent.removeElementByCopy(stud, index);
		System.out.println("删除成功!");
	}
	public static StudIn[] removeElementByCopy(StudIn[] array, int position) {  
        if (position < 0 || position > array.length) {  
            throw new IndexOutOfBoundsException("the position is out of the array indices");  
        }  
        StudIn[] newArray = new StudIn[array.length - 1];  
        int index = position - 1;  
        System.arraycopy(array, 0, newArray, 0, index);  
        if (index < array.length - 1) {  
            System.arraycopy(array, index + 1, newArray, index, array.length - index - 1);  
        }  
        return newArray;  
    }  

	@Override
	public void delete(String name) {
		// TODO Auto-generated method stub
		int flag=-1;
		for(int i=0;i<cout;i++){
			if(stud[i].getName().equals(name)){
				cout=cout-1;
				stud=ArrStudent.removeElementByCopy(stud, i+1);
				System.out.println("删除成功!");
				flag=1;
			}
			if(flag==-1){
				System.out.println("没找到该学生信息!");
			}
		}
		
	}

	@Override
	public void search(String name) {
		// TODO Auto-generated method stub
		int flag=-1;
		for(int i=0;i<cout;i++){
			if(stud[i].getName().equals(name)){
				System.out.println(stud[i].toString());
				flag=1;
				break;
			}
			if(flag==-1){
				System.out.println("没有找到该学生信息");
			}
			
		}
	}

}
import java.io.*;
public class ArrStudentUser {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArrStudent stud=new ArrStudent(10);
//		ArrStudent stud=new ArrStudent();
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		while(true){
			System.out.println("********学生信息管理系统********");
			System.out.println("1 添加纪录");
			System.out.println("2 显示所有记录");
			System.out.println("3 查询记录");
			System.out.println("4 删除记录");
			System.out.println("5 获取学生记录个数");
			System.out.println("6 输入学生姓名查询学生记录");
			System.out.println("7 输入学生姓名删除学生记录");
			System.out.println("0 退出\n");
			System.out.print("输入你的选择:");
			try {
				int choice=Integer.parseInt(br.readLine());
				switch (choice) {
				case 0:
					System.exit(0);
					break;
				case 1:
					System.out.println("输入学生姓名:");
					String Sname=br.readLine().toString();
					System.out.println("输入学生学号:");
					int Sid=Integer.parseInt(br.readLine());
					System.out.println("输入学生成绩:");
					int Sscore=Integer.parseInt(br.readLine());
					StudIn sd=new StudIn(Sname, Sid, Sscore);
					stud.add(sd);
					System.out.println("信息添加完毕!");
					break;
				case 2:
					System.out.println("姓名:\t学号:\t成绩:");
					try{stud.listAll();
					}catch(NullPointerException e){
						e.printStackTrace();
					}
					break;
				case 3:
					System.out.println("输入学生的位置序号:");
					int index=Integer.parseInt(br.readLine());
					stud.search(index);
					break;
				case 4:
					System.out.println("输入记录序号:");
					int index1=Integer.parseInt(br.readLine());
					stud.delete(index1);
					break;
				case 5:
					System.out.println("学生记录个数为:"+stud.getCounts());
					break;
				case 6:
					System.out.println("输入学生姓名:");
					String Sname1=br.readLine();
					stud.search(Sname1);
					break;
				case 7:
					System.out.println("输入学生姓名:");
					String Dname=br.readLine();
					stud.delete(Dname);
					break;
				default:
					break;
				}
			} catch (NumberFormatException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
//			finally {
//				if(null!=br){
//					try {
//						br.close();
//					} catch (IOException e) {
//						// TODO Auto-generated catch block
//						e.printStackTrace();
//					}
//				}
//			}
			
		}
		
		
	}

}

三、链表:使用链式存储结构存储数据的线性表称为链表

        分为:单链表、双链表、循环单链表、双向循环链表。

        Java类库中链表:LinkedList类是一个双向链表结构,可用来作为单链表或双向链表使用

     

带头结点的循环单链表

CircList.h

//
// Created by zhangzhiqiang on 2020/7/5.
//

#ifndef DATASTRUCTURE_CIRCLIST_H
#define DATASTRUCTURE_CIRCLIST_H
#include <iostream>
using namespace std;
class LinkNode{//单链表结点
public:
    LinkNode *link;//指针域
    int data;//数据域
};

//带头结点的循环单链表
class CircList{
private:
    LinkNode *first,*last;//first指向头结点,last指向尾结点
public:
    CircList();//构造函数
    bool Insert(int &x);//将新元素x插入
    bool Remove(int i,int &x);//删除第i个位置的结点(i从1开始),将被删结点值通过引用类型x返回
    void Print();
};



#endif //DATASTRUCTURE_CIRCLIST_H


CircList.cpp

//
// Created by zhang zhiqiang on 2021/9/11.
//

#include "CircList.h"

//构造函数,初始化附加头结点的循环单链表
CircList::CircList() {
    LinkNode *headNode=new LinkNode;//分配一个头结点
    headNode->link=headNode;//link域存放的是头结点的地址
    first=headNode;//头指针指向头结点
    last=headNode;//尾指针指向头结点
}

//将新元素x插入到循环链表
bool CircList::Insert(int &x) {
    LinkNode *newNode=new LinkNode;//为新插入元素构建结点
    newNode->data=x;//数据域存放元素值
    //尾插法(新插入元素作为表尾)
    newNode->link=first;//新插入元素的结点作为尾结点,指向头结点
    last->link=newNode;//插入在最后一个结点后面
    last=newNode;//尾指针指向尾结点
    return true;
}

//删除第i个位置的结点(i从1开始),将被删结点值通过引用类型x返回
bool CircList::Remove(int i, int &x) {
    LinkNode *current;//被删除结点的前一个结点
    LinkNode *del;//被删除结点
    current=first;//先将结点指向头结点,然后遍历寻找第i个位置的前一个结点
    for (int j = 0; j < i-1; ++j) {
        current=current->link;
    }
    del=current->link;//找到删除结点
    x=del->data;//保存删除结点的元素值
    if(del==last){//删除位置为表尾结点
        current->link=first;//则current变成表尾,让其指向头结点
        last=current;//修改表尾指针
    }else{
        current->link=del->link;//重新拉链,表尾指针不变
    }
    delete del;//删除结点
    return true;
}

//打印链表元素
void CircList::Print() {
    LinkNode *current=first->link;
    do{
        cout<<current->data<<",";
        current=current->link;
    }while (current->link!=first);
    cout<<last->data;

}

顺序表

SeqList.h

//
// Created by zhangzhiqiang on 2020/5/16.
//

#ifndef DATASTRUCTURE_SEQLIST_H
#define DATASTRUCTURE_SEQLIST_H
#include <cstdlib>
#include <iostream>

//顺序表
struct SeqList{
private:
    int *data;//定义int型指针用于动态分配数组
    int maxSize;//顺序表的最大容量
    int last;//当前已存表项的最后位置(从0开始),表空时为-1
public:
    SeqList(int size);//构造函数,size为初始化顺序表的大小
    bool IsFull();//判满
    bool IsEmpty();//判空
    bool Insert(int i,int x);//将新元素x插入到第i个位置后面
    bool Remove(int i,int &x);//删除第i个位置的元素,并通过引用类型x返回其值
    void ReSize(int newSize);//扩充顺序表,使其新数组的元素个数为newSize
};

#endif //DATASTRUCTURE_SEQLIST_H





SeqList.cpp

//
// Created by zhang zhiqiang on 2021/9/11.
//

#include "SeqList.h"

//构造函数(初始化)
SeqList::SeqList(int size) {
    maxSize=size;
    last=-1;//设置表长为空
    data=new int[size];
}
//判满
bool SeqList::IsFull() {
    return last == maxSize - 1;
}
//判空
bool SeqList::IsEmpty() {
    return last==-1;
}
//插入
bool SeqList::Insert(int i, int x) {
    if(IsFull() || i<0 || i>last+1 ){//判表满、参数i是否合理,(i>last+1)表示只能顺序存储
        return false;
    }else{
        for (int j = last; j >= i ; j--) {
            data[j+1]=data[j];//先依次后移,空出第i号位置
        }
        data[i]=x;//这里注意,若定义数组 int a[10],表示10个元素,但使用数组时,下标是0~9
        last++;//最后位置加1
        return true;
    }
}
//删除
bool SeqList::Remove(int i, int &x) {
    if (IsEmpty() || i<1 ||i>last+1){//判表空、参数i是否合理
        return false;
    }else{
        x=data[i-1];//保存第i个被删元素
        for (int j = i; j <= last; j++) {
            data[j-1]=data[j];//依次往前移,填补
        }
        last--;//最后位置减1
        return true;
    }
}
//扩充顺序表,新数组元素个数为newSize
void SeqList::ReSize(int newSize) {
    if (newSize <= 0 || newSize == maxSize) {//检查参数的合理性
        std::cout << "无效的数组大小\n";
    } else {
        int *newArray = new int[newSize];//建立新数组
        int n = last + 1;//记录原数组长度为n
        int *srcptr = data;//原数组首地址
        int *destptr = newArray;//新数组首地址
        while (n--) {
            *destptr++ = *srcptr++;//复制元素
        }
        delete[]data;//删老数组
        data = newArray;//复制新数组
        maxSize = newSize;
    }
}

带头结点的单链表

SinList.h
//
// Created by zhangzhiqiang on 2020/7/5.
//

#ifndef DATASTRUCTURE_SINLIST_H
#define DATASTRUCTURE_SINLIST_H

#include <iostream>

//单链表结点
struct LinkNode{
    int data;//数据域
    LinkNode *link;//指针域
};

//带头结点的单链表
class SinList{
private:
    LinkNode *first;//指向头结点的指针
public:
    SinList();//构造函数
    bool Insert(int &x);//将新元素x插入
    bool Remove(int i,int &x);//删除第i个位置的结点(i从1开始),将被删结点值通过引用类型x返回
    void Print();
};


#endif //DATASTRUCTURE_SINLIST_H




SinList.cpp

//
// Created by zhang zhiqiang on 2021/9/11.
//

#include "SinList.h"

//附加头结点的单链表构造函数
SinList::SinList() {
    LinkNode *headNode=new LinkNode;
    headNode->link=nullptr;
    first=headNode;
}
//插入新元素x
bool SinList::Insert(int &x) {
    LinkNode *newNode=new LinkNode;//为新插入元素构造结点
    newNode->data=x;//数据域为元素值
    //将新结点放在头结点的后面(不必区分在单链表头部或中部、尾部插入)
    newNode->link=first->link;
    first->link=newNode;
    return true;
}
//删除第i个位置的结点(i从1开始),将被删结点值通过引用类型x返回
bool SinList::Remove(int i, int &x) {
    LinkNode *del;//被删结点的指针
    LinkNode *current;//被删除结点的前一个结点
    current=first;//先将结点指向头结点,然后遍历寻找第i个位置的前一个结点
    for (int j = 0; j <i-1 ; ++j) {
        current=current->link;
    }
    del=current->link;//保存被删除结点
    current->link=del->link;//重新拉链
    x=del->data;//保存被删结点元素
    delete del;//删除del指向的结点
    return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值