第一章 绪论
1.1 什么是数据结构
1.1.1 数据结构的逻辑定义
数据结构:(1)数据元素之间的逻辑关系(数据的逻辑结构)
(2)数据元素及其关系在计算机存储器中的存储方式(数据的存储结构)
(3)施加在数据上的操作(数据的运算)
数据:可被计算机识别并加工处理的对象
1.1.2 数据的逻辑结构
逻辑结构的表示:表格、图等容易理解的形式
1.1.3 数据的存储结构
数据及数据之间的关系在计算机中的存储方式(正确反映数据元素之间的逻辑关系)
1.顺序存储结构
2.链式存储结构
1.1.4 数据的运算
运算描述+运算实现
1.1.5 数据结构和数据类型
ADT抽象数据类型名{
数据对象:数据对象的声明
数据关系:数据关系的声明
基本运算:基本运算的声明--基本运算名(参数表):运算功能描述
}
1.2 算法及其描述
1.2.1 什么是算法
1.2.2 算法描述
程序=数据结构+算法
1.3 算法分析
1.3.1 算法设计要求
1.3.2 算法的时间性能分析
1.计算算法频度
2.算法的最好、最坏和平均时间复杂度
1.3.3 算法的存储空间分析
抽象数据类型=数据的逻辑结构(-->成员变量)+抽象运算(-->公有方法)
第二章 线性表
2.1 线性表的定义
定义:具有相同特性的数据元素的一个有限序列
2.1.1 什么是线性表
2.1.2 线性表的抽象数据类型描述
2.2 线性表的顺序存储结构
2.2.1 线性表的顺序存储结构--顺序表
public class SqListClass<E> { //顺序表泛型类
final int initcapacity = 10; //顺序表的初始容量(常量)
public E[] data; //存放顺序表中元素
public int size; //存放顺序表的长度
private int capacity; //存放顺序表的容量
public SqListClass() { //构造方法,实现data和length的初始化
data = (E[]) new Object[initcapacity]; //强制转换为E类型数组
capacity = initcapacity;
size = 0;
}
}
2.2.2 线性表的基本运算算法在顺序表中的实现
二路归并
public class Main {
public static SqListClass<Integer> Merge2(SqListClass<Integer> A, SqListClass<Integer> B) {
SqListClass<Integer> C = new SqListClass<Integer>();
int i = 0; //i:遍历A
int j = 0; //j遍历B
while (i < A.size() && j < B.size()) {
if (A.GetElem(i) < B.GetElem(j)) {
C.Add(A.GetElem(i)); //较小的A元素+C
i++;
} else {
C.Add(B.GetElem(j)); //较小的B元素+C
j++;
}
}
while (i < A.size) { //若A未遍历完全
C.Add(A.GetElem(i));
i++;
}
while (j < B.size()) { //若B未遍历完全
C.Add(B.GetElem(j));
j++;
}
return C;
}
public static void main(String[] args){
//1.创建递增的顺序表a
Integer[] a={1,3,5,7};
SqListClass<Integer> A=new SqListClass<>();
A.CreateList(a);
System.out.println("A:"+A);
//2.创建增的顺序表b
Integer[] b={1,2,5,7,9,10,20};
SqListClass<Integer> B=new SqListClass<>();
B.CreateList(b);
System.out.println("B:"+B);
//3.执行二路归并算法代码
System.out.println("二路归并");
SqListClass<Integer> C= Ex2_6.Merge2(A,B);
System.out.println("C:"+C);
}
}
2.2.4 顺序表容器--ArrayLiist
1.ArrayList的基本应用
2.ArrayList类元素的排序:
(1)按元素递增排序:Collections.sort(myarrlist);
(2)按元素递减排序:Collections.sort(myarrlist,Collections.reverseOrder());
2.3 线性表的链式存储结构
2.3.1 线性表的链式存储结构--链表
指针成员:一个结点中包含有后继结点的地址信息或者前驱结点的地址信息
单链表:只设置一个指向其后继结点的指针成员
双链表:每个结点设置两个指针成员,分别指向其前驱结点和后继结点
2.3.2 单链表
public class LinkNode<E>{//单链表结点泛型类
E data;//结点的指针域
LinkNode<E>next;//后继结点的指针域
public LinkNode(){//构造方法
next=null;
}
public LinkNode(E d){//重载构造方法
this.data=d;
this.next=null;
}
}
public class LinkListClass<E> {
//单链表泛型类
public LinkNode<E> head;//存放头结点
public LinkListClass() {//构造方法
this.head = new LinkNode<E>();//创建头结点
this.head.next = null;
}
//1.头插法
public void CreateListF(E[] a){
LinkNode<E> s;
for (int i = 0;i<a.length;i++){
s = new LinkNode<E>(a[i]);
s.next = head.next;
head.next = s;
}
}
//2.尾插法
public void CreateListR(E[] a){
LinkNode<E> s,t = head;
for (int i=0;i<a.length;i++){
s = new LinkNode<E>(a[i]);
t.next = s;
t=s;
}
t.next = null;
}
//线性表的基本运算算法
private LinkNode<E> geti(int i){//返回序号为i的结点
LinkNode<E> p =head;
int j = -1;
while (j<i){
j++;
p=p.next;
}
return p;
}
//1)将元素e添加到线性表的末尾:Add(e)
public void Add(E e){
LinkNode<E> s = new LinkNode<E>(e);
LinkNode<E> p = head;
while (p.next!=null){ //查找尾结点p
p=p.next;
}
p.next=s;
}
//2)求线性表的长度
public int size(){
LinkNode<E> p = head;
int cnt = 0;
while (p.next!=null){
cnt++;
p=p.next;
}
return cnt;
}
//3)设置线性表的长度
public void Setsize(int nlen){
int len = size();
if (nlen<0||nlen>len){
throw new IllegalArgumentException("设置长度:n不在有效范围内");
}
if (nlen==len){
return;
}
LinkNode<E> p = geti(nlen-1);
p.next = null;
}
//4)求线性表中序号为i的元素
public E GetElem(int i){
int len = size();
if(i<0||i>len-1){
throw new IllegalArgumentException("查找:位置i不在有效范围内");
}
LinkNode<E> p = geti(i);
return (E)p.data;
}
//5)设置线性表中序号为i的元素
public void SetElem(int i,E e){
if (i<0||i>size()-1){
throw new IllegalArgumentException("设置:位置i不在有效范围内");
}
LinkNode<E> p = geti(i);
p.data = e;
}
//6)求线性表中第一个值为e的元素的逻辑序号
public int GetNo(E e){
int j = 0;
LinkNode<E> p = head.next;
while (p!=null&&!p.data.equals(e)){
j++;
p=p.next;
}
if (p==null){
return -1;
}else {
return j;
}
}
//7)将线性表中序号为i和序号为j的元素交换
public void swap(int i ,int j){
LinkNode<E> p = geti(i);
LinkNode<E> q = geti(j);
E tmp = p.data;
p.data = q.data;
q.data = tmp;
}
//8)在线性表中插入e作为第i个元素
public void Insert(int i ,E e){
if (i<0||i>size()){
throw new IllegalArgumentException("插入:位置i不在有效范围内");
}
LinkNode<E> s = new LinkNode<E>(e);
LinkNode<E> p = geti(i-1);
s.next = p.next;
p.next = s;
}
//9)在线性表中删除第i个数据元素
public void Delete(int i){
if (i<0||i>size()-1){
throw new IllegalArgumentException("删除:位置i不在有效范围内");
}
LinkNode<E> p = geti(i-1);
p.next=p.next.next;
}
@Override
public String toString() {
String ans = "";
LinkNode<E> p = head.next;
while (p!=null){
ans+=p.data+"";
p=p.next;
}
return ans;
}
}
2.3.3 双链表
class DLinkNode<E> {
E data;
DLinkNode<E> prior; //区别:前驱结点指针
DLinkNode<E> next;
public DLinkNode(){
prior=null;
next=null;
}
public DLinkNode(E d) {
data = d;
prior = null;
next = null;
}
}
public class DLinkListClass<E> {
DLinkNode<E> dhead;
public DLinkListClass(){
dhead=new DLinkNode<E>();
dhead.prior=null;
dhead.next=null;
}
//头插法:数组a建立双链表
public void CreateListF(E[] a){
DLinkNode<E> s;
for(int i=0;i<a.length;i++){
s=new DLinkNode<E>(a[i]);
s.next=dhead.next;
if(dhead.next!=null){
dhead.next.prior=s;
}
dhead.next=s;
s.prior=dhead;
}
}
//尾插法
public void CreateListR(E[] a){
DLinkNode<E> s,t;
t=dhead;
for(int i=0;i<a.length;i++){
s=new DLinkNode<E>(a[i]);
t.next=s;
s.prior=t; t=s;
}
t.next=null;
}
public void Add(E e){
DLinkNode<E> s = new DLinkNode<E>(e);
DLinkNode<E> p = dhead;
while (p.next!=null){
p=p.next;
}
p.next=s;
}
public int size(){
DLinkNode<E> p = dhead;
int cnt = 0;
while (p.next!=null){
cnt++;
p=p.next;
}
return cnt;
}
private DLinkNode<E> geti(int i){
DLinkNode<E> p = dhead;
int j = -1;
while (j<i){
j++;
p=p.next;
}
return p;
}
public void Setsize(int nlen){
int len = size();
if (nlen<0||nlen>len){
throw new IllegalArgumentException("设置长度:n不在有效范围内");
}
if (nlen==len){
return;
}
DLinkNode<E> p = geti(nlen-1);
p.next=null;
}
public E GetElem(int i){
int len = size();
if (i<0||i>len-1){
throw new IllegalArgumentException("查找:位置i不在有效范围内");
}
DLinkNode<E> p = geti(i);
return (E)p.data;
}
public void SetElem(int i,E e){
if (i<0||i>size()-1){
throw new IllegalArgumentException("设置:位置i不在有效范围内");
}
DLinkNode<E> p = geti(i);
p.data=e;
}
public int GetNo(E e){
int j=0;
DLinkNode<E> p = dhead.next;
while (p!=null&&!p.data.equals(e)){
j++;
p=p.next;
}
if (p==null){
return -1;
}
else {
return j;
}
}
public void Insert(int i,E e){
if(i<0 || i>size()){
throw new IllegalArgumentException("插入:位置i不在有效范围内");
}
DLinkNode<E> s=new DLinkNode<E>(e);
DLinkNode<E> p=geti(i-1);
s.next=p.next;
if(p.next!=null){
p.next.prior=s;
}
p.next=s;
s.prior=p;
}
public void Delete(int i){
if(i<0 || i>size()-1){
throw new IllegalArgumentException("删除:位置i不在有效范围内");
}
DLinkNode<E> p=geti(i);
if(p.next!=null){
p.next.prior=p.prior;
}
p.prior.next=p.next;
}
public static void Delx(DLinkListClass<Integer> L,Integer x){
DLinkNode<Integer> p=L.dhead.next;
while(p!=null && p.data!=x){
p=p.next;
}
if(p!=null){
if(p.next!=null){
p.next.prior=p.prior;
}
p.prior.next=p.next;
}
}
}
2.3.4 循环链表
public class CLinkListClass<E>{ //循环单链表泛型
LinkNode<E>head; //存放头结点
public CLinkListClass(){ //构造方法
head=new LinkNode<E>(); //创建头结点
head.next=head; //置为空的循环单链表
}
}
public class CDLinkListClass<E> { //循环双链表泛型
DLinkNode<E>dhead; //存放头结点
public CDLinkListClass(){ //构造方法
dhead=new DLinkNode<E>(); //创建头结点
dhead.prior=dhead; //构成空的循环双链表
dhead.next=dhead;
}
}
![](https://img-blog.csdnimg.cn/cc5628b2013444d19777c43f4d99e14c.png)
2.3.5 链表容器--LinkedList
LinkedList类对象和ArrayList类对象可以相互转换
2.4 顺序表和链表的比较
2.5 线性表的应用
2.5.1 求解两个多项式相加问题的描述![](https://img-blog.csdnimg.cn/a054dd62075b46b890652ab0828a8c38.png)
2.5.2 采用顺序存储结构求解
2.5.3 采用链式存储结构求解![](https://img-blog.csdnimg.cn/3a5e11679cba4617846817dbc90ea549.png)