顺序表与链表
1.线性表:
是一种在实际中广泛使用的数据结构,n个具有相同的数据元素的有限序列
常见的线性表:顺序表,链表,栈,队列,字符串
在物理结构上不一定是连续的,在物理存储时,通常以数组和链式结构的形式存储
2.顺序表
顺序表使用一段物理地址连续的存储单元一次存储数据元素的数据结构
采用数组存储
分类:静态数据表:使用定长数组存储
动态数据表:使用动态开辟的数组存储
import java.util.Arrays;
public class MyArrayList {
public static void main(String[] args) {
M m = new M() ;
m.add(2,3);
m.add(1,5);
m.add(3,4);
m.add(0,1);
System.out.print(m.elem[0]+" ,");
System.out.print(m.elem[1]+",");
System.out.print(m.elem[2]+",");
System.out.println(m.elem[3]);
System.out.println("=====");
System.out.println( m.contains(3));
System.out.println("=======");
System.out.println(m.search(3));
System.out.println("=======");
System.out.println(m.getPos(3));
System.out.println("=======");
m.setPos(2,3);
System.out.println("=======");
m.remove(3);
m.clear();
System.out.println(m.size());
}
}
class M {
public int usedSize;//实际存入的数据占用空间的大小
public int[] elem;//保存数据
public final int CAPACITY = 10;
public M() {
this.usedSize = 0;
this.elem = new int[CAPACITY];
}
//打印顺序表
public void display() {
for (int x : elem)
System.out.println(x);
}
//判断顺序表是否为满了
private boolean isFull() {
/* if (this.usedSize == this.elem.length)
{
return true;//满了
}
return false;*///没有满
return this.elem.length == this.usedSize;
}
//在pos位置新增元素
public void add(int pos, int data) {
if (isFull()) {
// this.elem = Arrays.copyOf(this.elem, this.elem.length*2);//增容申请新空间,拷贝数据,释放旧空间
int[] k= Arrays.copyOf( elem,elem.length*2);
this.elem=k;
}
//pos位置是否合法
if (pos < 0 || pos > this.elem.length) {
/*System.out.println("插入的位置不合法");
return;*/
throw new IndexOutOfBoundsException("pos位值不合法");
}
//挪数据
for (int i = usedSize - 1; i >= pos; i--) {
elem[i + 1] = elem[i];
}
//插入数据
elem[pos] = data;
usedSize++;
}
//判断是否包含某个元素
public boolean contains(int toFind) {
for (int x : this.elem) {
if (this.elem[toFind] == x) {
return true;//包含
}
}
return false;//不包含
}
//判断顺序表是否为空
private boolean isEmpty(){
if(usedSize==0){
return true;//为空
}
return false;//不为空
//return usedSize==0;
}
//判断某个元素对应的位置
public int search(int toFind) {
int m=0;
if(isEmpty())
{
System.out.println("顺序表为空");
} else {
for (int i = 0; i <= this.usedSize - 1; i++)
if (this.elem[i] == toFind)
return i;
}
return -1;//没有找到
}
//获取pos位置的元素
public int getPos(int pos) {
if (pos < 0 || pos > this.elem.length) {
return -1;
}
return this.elem[pos];
}
//给pos位置的元素设为value
public void setPos(int pos,int value){
this.elem[pos]=value;
System.out.println(this.elem[pos]);
}
//删除第一次出现的关键字
public void remove(int toRemove){
int b=this.search(toRemove);
if(b==-1){
System.out.println("没有找到");
return ;
}
//删除
for(int i=b;i<usedSize-1;i++){
elem[i]=elem[i+1];
}
usedSize--;
}
//获取顺序表的长度
public int size( ){
return this.usedSize;
}
//清空顺序表
public void clear(){
this.usedSize=0;
}
}
3.链表
链表是一种物理结构上非连续存储结构,数据元素的逻辑顺序是通过链表的引用链接次序实现的
有8中链表结构
//节点类
class ListNode{
public int data;
public ListNode next;//下一个节点
ListNode(int data){
this.data=data;
this.next=null;
}
}
//单链表类
class MySignalList {
public ListNode head;//头节点
MySignalList() {
this.head = null;
}
//头插法
public void addFirst(int data) {
ListNode node=new ListNode(data);
if(this.head==null){
this.head=node;
}else{
node.next=head;
head=node;
}
}
//尾插法
public void addLast(int data) {
ListNode node=new ListNode(data);
ListNode cur=this.head;
if(this.head==null){
this.head=node;
}
while(cur.next!=null){
cur=cur.next;
}
cur.next=node;
}
//单链表的长度
public int getLength() {
int count=0;
ListNode cur=head;
while(cur!=null){//节点不为空
count++;
cur=cur.next;
}
return count;
}
//找cur-1的位置
private ListNode searchIndex(int index) {
ListNode cur=head;
int count=0;
while(count<index-1){
cur=cur.next;
count++;
}
return cur;
}
//任意位置插入,第一个节点为0号下标
public boolean addIndex(int index, int data) {
if(index<0||index>getLength()){
System.out.println(“插入位置不合法”);
return false;
}
if(index0){
addFirst(data);
return true;
}
//找到index-1 的位置
ListNode cur=searchIndex(index);
ListNode node =new ListNode(data);
//插入节点
node.next=cur.next;
cur.next=node;
return true;
}
//疑问
//查找关键字key是否在单链表中
public boolean contains(int key) {
ListNode cur=this.head;
while(cur!=null){
if(cur.datakey){
return true;
}
cur=cur.next;
}
return false;
}
public void display() {
ListNode cur = this.head;
while (cur != null) {
System.out.print(cur.data+" ");
cur = cur.next;
}
System.out.println();
}
//找到key的前驱
private ListNode searchPrev(int key) {
ListNode cur=this.head;
while( cur.next!=null){
if(cur.next.data==key){
return cur;
}
cur=cur.next;
}
return null;
}
//删除第一次出现关键字为key 的节点
public void remove(int key) {
//判断是否为空链表
if (this.head == null) {
System.out.println("单链表为空");
}
//删除的节点为头节点
if (this.head.data == key) {
this.head = this.head.next;
return;
}
ListNode cur = searchPrev(key);
ListNode del = cur.next;
//删除
cur.next = del.next;
}
//删除所有关键字为key的节点
public void removeKey(int key) {
if(this.head.datakey){
this.head=this.head.next;
return ;
}
ListNode cur=this.head;
ListNode pre=this.head.next;
while(cur.next!=null){//不能写成 cur,要不if语句会出现空指针异常
if(cur.next.datakey){
cur.next=pre.next;
//pre=pre.next;
}else{
cur=pre;
pre=pre.next;
}
}
}
//头插法
//prev 重点 反转
//在反转前一定要保存下一个节点
public ListNode reverseList() {
ListNode prev = null;//前一个节点
ListNode newHead=null;
ListNode cur = this.head;//头节点
while (cur!= null) {
ListNode curNext = cur.next;//保留下一个节点
if (curNext == null) {
newHead = cur;
}
cur.next = prev;//指针反转
prev = cur;//前节点后移
cur = curNext;//当前节点后移
}
return newHead;
}
public void display1(ListNode newHead) {
ListNode cur = newHead;
while (cur!= null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
Sy stem.out.println();
}
//输出中间节点 当链表为偶数的时候,返回两个节点中前一个节点;
//1.用两个指针遍历单链表,一个快指针,一个慢指针
//2.快指针每次向前移动两个节点,慢指针向前移动一个节点
//3.当快指针移动到链表结尾的时候,慢指针所在的位置就是中间节点的位置
public ListNode middleNode() {
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//输入一个链表,输出倒数第k个节点
//两个指针,第一个节点向前移动k-1次,之后两个节点共同移动
//当前面的指针到达末尾的时候,后面的指针所在的位置就是倒数第k个节点
public ListNode m(int k) {
if (k < 0 || k > getLength()) {
System.out.println(" k不合法");
}
ListNode fast = this.head;
ListNode slow = this.head;
while (k - 1 > 0) {//前移k-1步
if (fast.next != null) {
fast = fast.next;
k–;
}//else{
//System.out.println(“没有这个节点”);
}
while (fast.next != null) {//共同移动
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
//以x为基准将单链表分开成两部分
public ListNode partition(int x) {
ListNode cur = this.head;
ListNode beforeStart = null;
ListNode beforeEnd = null;
ListNode afterStart = null;
ListNode afterEnd = null;
while (cur != null) {//遍历单链表
/ListNode curNext = c ur.next;
cur.next = null;/
if (cur.data < x) {
if (beforeStart == null) {
beforeStart = cur;
beforeEnd = beforeStart;
} else {
beforeEnd.next = cur;
beforeEnd = beforeEnd.next;
}
} else {
if (afterStart == null) {
afterStart = cur;
afterEnd = afterStart;
} else {
afterEnd.next = cur;
afterEnd = afterEnd.next;
}
}
cur = cur.next;
}
if (beforeStart == null) {
return afterStart;
}
beforeEnd.next = afterStart;
if (afterStart != null) {
afterEnd.next = null;
}
return beforeStart;
}
//删除重复节点
public ListNode deleteDuplication() {
ListNode node = new ListNode(-1);//虚拟节点
ListNode cur = this.head;
ListNode tmp = node;
while (cur != null) {
if (cur.next != null && cur.data == cur.next.data) {
while (cur.next != null && cur.data == cur.next.data) {//cur要多走一步
cur = cur.next;
}
cur = cur.next;
} else {
tmp.next = cur;// 没有重复的节点
cur = cur.next;
tmp = tmp.next;
}
}
temp.next=null;
return node.next;
}
//回文结构
public boolean chkPalindrome() {
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {//找到中间节点
slow = slow.next;
fast = fast.next.next;
}
//反转
ListNode p = slow.next;
while (p != null) {
ListNode pNext = p.next;
p.next = slow;
slow = p;
p = pNext;
}
while (slow != this.head) {
if (slow.data != head.data) {
return false;
}
if (this.head == slow) {
return true;
}
slow = slow.next;
head = head.next;
}
return true;
}
//判断是否有环
public boolean hasCycle() {
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;//fast走两步
slow = slow.next;//slow走一步
if (slow == fast) {
break;
}
}
if (fast == null || fast.next == null) {//没有环
return false;
}
return true;
}
//环
public void createLoop() {
ListNode cur = this.head;
while (cur.next != null) {
cur = cur.next;
}
cur.next=this.head.next;
}
//找到环的入口 slow=this.head; slow=slow.next; fast=fast.next;
public ListNode detectCycle() {
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (slow == fast) {
break;
}
}
if (fast == null || fast.next == null) {//没有环
return null;
}
slow = this.head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return fast;
}
//
public int listen() {
if(head==null){
return -1;
}
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (slow == fast) {
break;
}
}
if (fast == null || fast.next == null) {//没有环
return -1;
}
int count=1;
slow=slow.next;
while (slow != fast) {
slow = slow.next;
count++;
}
return count ;
}
}
public class Test1 {
public static void main(String[] args) {
MySignalList mySignalList=new MySignalList();
mySignalList.addIndex(0,12);
mySignalList.addIndex(1,13);
mySignalList.addIndex(2,17);
mySignalList.addIndex(3,13);
mySignalList.addIndex(0, 12);
/* MySignalList pL = new MySignalList();
pL.addLast(12);
pL.addLast(13);
pL.addLast(14);
pL.addLast(15);
MySignalList pS = new MySignalList();
pS.addLast(12);
pS.addLast(12);
pS.addLast(12);
pS.addLast(12);*/
//mySignalList.contains(19);
// mySignalList.remove(13);
// mySignalList.display ();
// mySignalList.removeKey(13);
mySignalList.display();
mySignalList.middleNode();
// ListNode newHead=mySignalList.reverseList();
//mySignalList.display1( newHead);
// ListNode node= mySignalList.partition(13);
//mySignalList.display1(node);
// ListNode node1= mySignalList.deleteDuplication();
//mySignalList.display1(node1);
//mySignalList.chkPalindrome();
//mySignalList.createLoop();
//mySignalList.hasCycle();
//mySignalList.detectCycle();
// mySignalList.listen();
}
//相交
public static ListNode getIntersection(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
//永远指向最远的单链表
ListNode pL = headA;
//永远指向最短的单链表
ListNode pS = headB;
int lenA = 0;
int lenB = 0;
//分别求长度
while (pL != null) {
pL = pL.next;
lenA++;
}
while (pS != null) {
pS = pS.next;
lenB++;
}
//求长度的差值
int len = lenA - lenB;
if (len < 0) {
pL = headB;
pS = headA;
len = lenB - lenA;
}
while (len > 0) {
pL = pL.next;
len--;
}
//走完len之后两个开始同时走
//一直走直到next相同就是节点
while (pL != pS && pL != null) {
pL = pL.next;
pS = pS.next;
}
if (pL == pS && pS != null) {
return pL;
}
return null;
/* while(pL.next!=pS.next){
pL=pL.next;
pS=pS.next;
}*/
//万一没有相交,并且两个单链表长度一样
//防止最后一个节点
/*if (pL.next == pS.next && pL.next != null) {
return pL.next;
}
return null;*/
}
public void createCut(ListNode headA, ListNode headB) {
headA.next.next= headB.next.next.next;
}
//合并两个有序的单链表
public ListNode mergeTowLists(ListNode headA, ListNode headB) {
//curA curB
ListNode node = new ListNode(-1);
ListNode tmp = node;
while (headA != null && headB != null) {
if (headA.data < headB.data) {
tmp.next = headA;
headA = headA.next;
tmp = tmp.next;
} else {
tmp.next = headB;
headB = headB.next;
tmp = tmp.next;
}
}
if (headA != null) {
tmp.next = headA;
}
if (headB != null) {
tmp.next = headB;
}
return node.next;
}
}