packagepers.ty.$1101datastructure;importjava.util.Hashtable;/***@authorAdministrator
* 实现单链表的基本操作,增加删除节点、排序、打印、计算长度*/
public classMyLinkedList {
Node head= null;//链表头的作用
/**向链表中插入数据
*@paramd:插入数据的内容*/
public void addNode(intd){
Node newNode=newNode(d);if(head==null){
head=newNode;return;
}
Node tmp=head;while(tmp.next!=null){
tmp=tmp.next;
}//add Node to end
tmp.next=newNode;
}/***@paramindex:删除第index个节点
*@return成功返回true,失败返回false*/
public Boolean deleteNode(intindex){if(index<1||index>length()){return false;//删除元素位置不合理
}//删除链表中的第一个元素
if(index==1){
head=head.next;return true;
}int i=1;
Node preNode=head;
Node curNode=preNode.next;while(curNode!=null){if(i==index){
preNode.next=curNode.next;return true;
}
preNode=curNode;
curNode=curNode.next;
i++;
}return true;
}/***@return返回链表的长度length*/
public intlength(){int length=0;
Node tmp=head;while(tmp!=null){
length++;
tmp=tmp.next;
}returnlength;
}/*** 对链表进行排序
*@return返回排序后的头结点*/
publicNode orderList(){
Node nextNode=null;int temp=0;
Node curNode=head;while(curNode.next!=null){
nextNode=curNode.next;while(nextNode!=null){if(curNode.data>nextNode.data){
temp=curNode.data;
curNode.data=nextNode.data;
nextNode.data=temp;
}
nextNode=nextNode.next;
}
curNode=curNode.next;
}returnhead;
}/*** 打印链表中所有数据*/
public voidprintList(){
Node tmp=head;while(tmp!=null){
System.out.print(tmp.data+" ");
tmp=tmp.next;
}
System.out.println();
}/*** 从链表中删除数据的第一种方法
* 遍历链表,把遍历到的数据存到一个Hashtable中,在遍历过程中若当前访问的值在Hashtable
* 中存在,则可以删除
* 优点:时间复杂度低 缺点:需要额外的存储空间来保存已访问过得数据*/
public voiddeleteDuplecate1(){
Hashtable table=new Hashtable();
Node tmp=head;
Node pre=null;while (tmp!=null) {if(table.containsKey(tmp.data))
pre.next=tmp.next;else{
table.put(tmp.data,1);
pre=tmp;
}
tmp=tmp.next;
}
}/*** 从链表中删除重复数据的第二种方法
* 双重循环遍历
* 优缺点很明显*/
public voiddeleteDuplecate2(){
Node p=head;while (p!=null) {
Node q=p;while(q.next!=null){if(p.data==q.next.data){
q.next=q.next.next;
}else{
q=q.next;
}
}
p=p.next;
}
}/***@paramk:找到链表中倒数第k个节点
*@return该节点
* 设置两个指针p1、p2,让p2比p1快k个节点,同时向后遍历,当p2为空,则p1为倒数第k个节点*/
public Node findElem(Node head,intk){if(k<1||k>this.length())return null;
Node p1=head;
Node p2=head;for (int i = 0; i < k-1; i++)
p2=p2.next;while (p2.next!=null) {
p2=p2.next;
p1=p1.next;
}returnp1;
}/*** 实现链表的反转
*@paramhead链表的头节点*/
public voidreverseIteratively(Node head){
Node pReversedHead=head;
Node pNode=head;
Node pPrev=null;while (pNode!=null) {
Node pNext=pNode.next;if(pNext==null)
pReversedHead=pNode;
pNode.next=pPrev;
pPrev=pNode;
pNode=pNext;
}this.head=pReversedHead;
}/*** 通过递归从尾到头输出单链表
*@paramhead*/
public voidprintListReversely(Node head){if(head!=null){
printListReversely(head.next);
System.out.print(head.data+" ");
}
}/*** 查询单链表的中间节点
* 定义两个指针,一个每次走一步,一个每次走两步...
*@paramhead
*@returnq为中间节点*/
publicNode searchMid(Node head){
Node q=head;
Node p=head;while (p!=null&&p.next!=null&&p.next.next!=null) {
q=q.next;
p=p.next.next;
}returnq;
}/*** 在不知道头指针的情况下删除指定节点
* 链表尾节点无法删除,因为删除后无法使其前驱节点的next指针置为空
* 其他节点,可以通过交换这个节点与其后继节点的值,然后删除后继节点
*@paramn
*@return
*/
public booleandeleteNode(Node n){if(n==null||n.next==null)return false;int tmp=n.data;
n.data=n.next.data;
n.next.data=tmp;
n.next=n.next.next;return true;
}/*** 判断两个链表是否相交
* 如果两个链表相交,则肯定有相同的尾节点,遍历两个链表,记录尾节点,看是否相同
*@paramh1链表1的头节点
*@paramh2链表2的头结点
*@return是否相交*/
public booleanisIntersect(Node h1,Node h2){if(h1==null||h2==null)return false;
Node tail1=h1;while (tail1.next!=null){
tail1=tail1.next;
}
Node tail2=h2;while(tail2.next!=null){
tail2=tail2.next;
}return tail1==tail2;
}/*** 找出相交的第一个节点
*@paramh1
*@paramh2
*@return
*/
publicNode getFirstMeetNode(Node h1,Node h2){if(h1==null||h2==null)return null;
Node tail1=h1;int len1=1;while (tail1.next!=null){
tail1=tail1.next;
len1++;
}
Node tail2=h2;int len2=1;while(tail2.next!=null){
tail2=tail2.next;
len2++;
}if(tail1!=tail2){return null;
}
Node t1=h1;
Node t2=h2;//找出较长的链表先遍历
if(len1>len2){int d=len1-len2;while(d!=0){
t1=t1.next;
d--;
}
}if(len1
t2=t2.next;
d--;
}
}while(t1!=t2){
t1=t1.next;
t2=t2.next;
}returnt1;
}public static voidmain(String[] args) {
MyLinkedList list=newMyLinkedList();
}
}