数据结构分类
1、线形结构:
- 都是非空集
- 有且仅有一个开始节点和结束节点
- 最多只有一个直接前趋结点和直接后继结点
- 线性表、栈、队列和串都是
2、非线性结构:
- 一个结点可以有多个前趋结点和后继结点
- 数组、广义表、树结构和图结构都是
存储方式
- 顺序存储:
- 在一块连续的存储区域一个接一个存放数据。逻辑上相连的结点放在物理位置相邻的单元里。
- 链接存储:
- 不要求逻辑相连的点物理位置也相连
- 附加字段表示下一个结点位置
- 索引存储方式:
- 稠密索引:一个结点在索引表只有一个索引
- 稀疏索引:一组结点只有一个索引
- 散列存储:
- 根据结点关键字直接计算结点的存储地址
常用结构
顺序表
线性表
定义:n(n>=0)个数据元素a1,a2,a3…an组成有限序列(可重复)
特点:每个元素类型长度一样,插入和删除任何一个,在这个元素之后的元素下标都要改变
实例:
data.java:
package Sequencelist;
public class data {
String key;
String name;
int age;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "data [key=" + key + ", name=" + name + ", age=" + age + "]";
}
}
SLType.java:
package Sequencelist;
public class SLType {
static final int MAXLEN = 10;
public data[] ListData = new data[MAXLEN + 1];//保存顺序表各个结点的数组
int ListLen;//顺序表已有结点长度
public void SLInit(SLType sl) {
sl.ListLen = 0;//初始化顺序表
}
public int SLLength(SLType sl) {
return sl.ListLen;
}
public int SLInsert(SLType sl, int n, data d) {
int i;
if (sl.ListLen > MAXLEN) {
System.out.println("sequence is full");
return 0;
}
if (n < 1 || n > sl.ListLen + 1) {
System.out.println("Wrong number");
return 0;//插入的序号不对
}
for (i = sl.ListLen; i >= n; i--) {
sl.ListData[i + 1] = sl.ListData[i];
}
sl.ListData[n] = d;//插入结点
sl.ListLen++;
return 1;
}
public int SLALL(SLType sl) {
int i;
for (i = 1; i <= sl.ListLen; i++) {
System.out.printf("data"+"["+i+"]"+":(%s,%d,%s)\n", sl.ListData[i].key, sl.ListData[i].age, sl.ListData[i].name);
}
return 0;
}
public int SLadd(SLType sl,data d) {
if(sl.ListLen>=MAXLEN) {
System.out.println("sequence is full");
return 0;
}
sl.ListData[++sl.ListLen]=d;
return 1;
}
public int SLdelete(SLType sl,int n) {
int i;
if(n<1||n>sl.ListLen) {
System.out.println("wrong number");
return 0;
}
for(i=n;i<sl.ListLen;i++) {
sl.ListData[i]=sl.ListData[i+1];//直接覆盖
}
sl.ListLen--;
return 1;
}
// 按照序号查找结点
public data slfindbynum(SLType sl,int n) {
if(n<1||n>sl.ListLen) {
System.out.println("wrong number");
return null;
}
return sl.ListData[n];
}
// 按照关键字
public int slfindbycont(SLType sl,String key) {
int i;
for(i=1;i<=sl.ListLen;i++) {
if(sl.ListData[i].key.compareTo(key)==0) {
return i;
}
}
return 0;
}
}
package Test;
import Sequencelist.SLType;
import Sequencelist.data;
import java.util.Scanner;
@SuppressWarnings("ALL")
public class SLtest {
public static void main(String[] args) {
// TODO Auto-generated method stub
int d,i,n=1;
data pda;
SLType sl=new SLType();
String key;
System.out.println("Here is sequence list's operation demo:");
sl.SLInit(sl);
System.out.println("Initialization completed!");
Scanner in=new Scanner(System.in);
do {
System.out.println("input the point's(key name age):");
data da=new data();
da.setKey(in.next());
da.setName(in.next());
da.setAge(in.nextInt());
if(da.getAge()!=0) {
if(sl.SLadd(sl,da)==0) {
break;
}
}
else {
break;
}
}while(true);
System.out.println(" All the sequence list's point:");
sl.SLALL(sl);
System.out.print("which point do you want to take?input it's serial number:-->");
i=in.nextInt();
pda=sl.slfindbynum(sl, i);
if(pda!=null) {
System.out.printf("the %d point is:(%d,%s,%s)",i,pda.getAge(),pda.getName(),pda.getKey());
}
System.out.printf("seach by key:");
key=in.next();
i=sl.slfindbycont(sl, key);
pda=sl.slfindbynum(sl, i);
if(pda!=null) {
System.out.printf("the %d point is:(%d,%s,%s)",i,pda.getAge(),pda.getName(),pda.getKey());
}
/*
* d=sl.SLLength(sl); System.out.println(d);
*/
}
}
链表
定义:结点之间不一定连续,每个结点包括引用和数据域
特点:数据域–结点实际数据;地址部分–下一个结点的地址;有头结点head指向第一个结点,最后一个结点的地址部分为null;
package Linklist;
public class data2 {
public String key;
public String name;
public int age;
}
package Linklist;
public class CLType {
public data2 nodeData=new data2();
public CLType nextNode;
public CLType CLAddEnd(CLType head,data2 nodeData){
CLType node,htemp;
if((node=new CLType())==null){
System.out.println("申请内存失败!");
return null;
}
else {
node.nodeData=nodeData;//数据域
node.nextNode=null;//表尾
if(head==null){
head=node;
return head;
}
htemp=head;
while (htemp.nextNode!=null){//查找链尾
htemp=htemp.nextNode;//htemp在不停移动
}
htemp.nextNode=node;//尾部插入结点
return head;
}
}
public CLType CLAddFirst(CLType head,data2 nodeData) {
CLType node;
if ((node = new CLType()) == null) {
System.out.println("申请内存失败!");
return null;
} else {
node.nodeData = nodeData;
node.nextNode = head;//指向头引用指向的结点,代替之前第一个结点
head = node;//头引用指向插入的新结点
return head;
}
}
public CLType CLFindNode(CLType head,String key){
CLType htemp;
htemp=head;
while (htemp!=null){
if(htemp.nodeData.key.compareTo(key)==0){
return htemp;
}
htemp=htemp.nextNode;
}
return null;
}
public CLType CLInsertNode(CLType head,String findkey,data2 nodeData){
CLType node,nodetemp;
if ((node = new CLType()) == null) {
System.out.println("申请内存失败!");
return null;
}
node.nodeData=nodeData;
nodetemp=CLFindNode(head,findkey);//得到要插入点位置
if (nodetemp!=null){
node.nextNode=nodetemp.nextNode;//新插入点指向目标点的下一结点
nodetemp.nextNode=node;//目标位置点指向插入点
}
else {
System.out.println("未找到正确位置!");
}
return head;
}
public int CLDeleteNode(CLType head,String key){
CLType node,htemp;
htemp=head;
node=head;
while (htemp!=null) {
if (htemp.nodeData.key.compareTo(key) == 0) {
node.nextNode = htemp.nextNode;//找到要删除的结点,使前一结点指向当前结点的下一结点,node代表前一个
return 1;
} else {
node = htemp;//node代表前一个结点
htemp = htemp.nextNode;
}
}
return 0;
}
public int CLlength(CLType head){
CLType htemp;
int len=0;
htemp=head;
while (htemp!=null){
len++;
htemp=htemp.nextNode;
}
return len;
}
public void CLALLNode(CLType head){
CLType htemp;
data2 nodeData;
htemp=head;
System.out.printf("当前链表共有%d个结点,链表数据如下:\n",CLlength(head));
while (htemp!=null){
nodeData=htemp.nodeData;
System.out.printf("结点(%s,%s,%d)",nodeData.key,nodeData.name,nodeData.age);
htemp=htemp.nextNode;
}
}
}
package Test;
import Linklist.CLType;
import Linklist.data2;
import java.util.Scanner;
public class LinkTest {
public static void main(String[] args) {
CLType node,head=null;
CLType cl=new CLType();
String key,findkey;
Scanner in=new Scanner(System.in);
System.out.println("输入数据,格式为:key name age");
do{
data2 nodeData=new data2();
nodeData.key=in.next();
if (nodeData.key.equals("0")){
break;
}
else {
nodeData.name=in.next();
nodeData.age=in.nextInt();
head=cl.CLAddEnd(head,nodeData);
}
}while (true);
cl.CLALLNode(head);
System.out.println("插入结点,请在下一行输入插入位置关键字:");
findkey=in.next();
System.out.println("输入结点的数据(key name age)");
data2 nodeData=new data2();
nodeData.key=in.next();
nodeData.name=in.next();
nodeData.age=in.nextInt();
head=cl.CLInsertNode(head,findkey,nodeData);
System.out.println("删除结点,输入要删除的关键字");
key=in.next();
cl.CLDeleteNode(head,key);
cl.CLALLNode(head);
System.out.println("链表中查找,输入关键字");
key=in.next();
node=cl.CLFindNode(head,key);
if (node!=null){
nodeData=node.nodeData;
System.out.printf("关键字%s对应结点(%s,%s,%d)\n",key,nodeData.key,nodeData.name,nodeData.age);
}
else {
System.out.println("链表没有相关关键字");
}
}
}
栈
顺序栈:
定义:用一组地址连续的内存单元存储数据,即定义一个数组,序号0元素就是栈底,top变量保存栈顶
特点:先进后出,只在栈顶端操作
入栈:先修改栈顶引用,让其上移一个位置,再保存数据到指定位置
出栈:同样先移动再保存
package Stack.Stacklist;
public class data3 {
public String name;
public int age;
}
package Stack.Stacklist;
public class StackType {
static final int MAXLEN=50;
data3[] data=new data3[MAXLEN+1];//结点
int top;//栈顶
public StackType STInit(){
StackType p;
if ((p=new StackType())!=null){
p.top=0;
return p;
}
return null;
}
public boolean STIsEmpty(StackType s){
boolean t;
t=(s.top==0);
return t;
}
public boolean STIsFull(StackType s){
boolean t;
t=(s.top==MAXLEN);
return t;
}
public void STCleat(StackType s){
s.top=0;
}
public void STFree(StackType s){
if(s!=null){
s=null;
}
}
public int Push(StackType s,data3 data3){
if(s.top+1>MAXLEN){
System.out.println("栈满溢出");
return 0;
}
s.data[++s.top]=data3;//先移动再赋值
return 1;
}
public data3 Pop(StackType s){
if(s.top==0){
System.out.println("栈空");
System.exit(0);
}
return (s.data[s.top--]);
}
public data3 ReadST(StackType s){
if(s.top==0){
System.out.println("空栈");
System.exit(0);
}
return (s.data[s.top]);
}
}
package Test;
import Stack.Stacklist.StackType;
import Stack.Stacklist.data3;
import java.util.Scanner;
public class StacklistTest {
public static void main(String[] args) {
StackType st=new StackType();
data3 data3=new data3();
StackType sta=st.STInit();
Scanner sc=new Scanner(System.in);
System.out.println("入栈");
System.out.println("输入(格式如此)-->: name age");
do {
data3 data31=new data3();
data31.name=sc.next();
if(data31.name.equals("0")){
break;//输入0退出
}
else{
data31.age=sc.nextInt();
st.Push(sta,data31);
}
}while (true);
String temp="1";
System.out.println("出栈,输入任意非0键继续:");
temp=sc.next();
while (!temp.equals("0")){
data3=st.Pop(sta);
System.out.printf("出栈数据-->(%s,%d)",data3.name,data3.age);
temp=sc.next();
}
System.out.println("演示结束");
st.STFree(st);
}
}