c2java 第1篇 泛型和双链表

本文探讨了使用C++与Java实现链表的底层原理,对比了两种语言在链表操作上的异同,并详细解释了泛型类、模板、宏在链表实现中的应用,以及如何通过链表实现基本操作如插入、删除和反转。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       上篇我对BigInteger 膜拜了一番,以为很复杂呢,结果看jdk带的源码,也就一个3000行java文件而已。因而右必要自己亲自写一些底层的东西。

一来是为了练手,二来是为了体会java的思维方式,三是比较C++的后继者们扬弃了什么。

 

废话不说,要点都写在注释里面了:

/*LinkedListTest.java --模仿C风格的双链表

1. head->func(head) 通过this变成head.func()。

2. C宏/模板 --> 泛型,在方法头上加
public  <T extends Comparable<? super T>>
public <T extends Comparable<T>>
虽然可以编译,但是不能调用这个类的其他方法。
通过搜索keywords:"Comparable generic type"
正确的办法是在泛型类定义时
 DNode<T> 改成 DNode<T extends Comparable<T>>
extends 表示限定。

* author ludi 2014.03*/ 
 class DNode<T extends Comparable<T>> {
	public T val;
	public DNode<T> next, prev;
	/*链表通常是双向的, 并且使得某些操作更简单*/

	public DNode(){
		/*创建链表头一般val置为空,当然我们也可以拿来当作链表个数*/
		val = null;
		next = prev = this;
	}

	public DNode(T item){
		val = item;
		next = prev = this;
	   /*这里为什么不是null? 
		* 目的是形成一个闭环,设链表最后一个节点是tail,
		* 则head->prev = tail; tail.next = head.
		* 闭环的优点是使后面的插入删除的操作不必判断指针是否为空*/	
	}

	/*因为参数是泛型<T>,只好把链表所有方法都放在DNode<T>里面了*/
	public String toString(){
		String str = "[";
		/*遍历模板:计数,查找,...*/
		DNode<T> curr = this.next;	
		while(curr != this){
			if(curr.val != null)str += curr.val.toString() + ", ";
			curr = curr.next;
		}
		str += "]";
		return str;
	}

	public DNode<T> indexOf( int idx){
		DNode<T> curr = this.next;
	
		for(; curr != this; curr = curr.next){
			if(0 == idx)break;
			--idx;
		}
		return (0 == idx) ? curr : null;
	}

	public void insertAfter(DNode<T> node, DNode<T> x){
		x.next = node.next;
		node.next.prev = x;
		x.prev = node;
		node.next = x;
	}
	
	public void insertTail( DNode<T> x){
		insertAfter(this.prev, x);
	}

	public DNode<T> deleteAfter(DNode<T> node){
		DNode<T> x = node.next;
		x.next.prev = node;
		node.next = x.next;
		return x;
	}
	/*上面的几个方法是基本操作,对于用作一般链表,链表形式的栈,队列已经足够了。
	 * 下面的仅仅是练习题目*/
	public void reverseList(){
		/*链表翻转, 类似于数组翻转。(如果是单链表,如何?)*/
		DNode<T> first = this.next, last = this.prev;
		while(first != last){
			T val = first.val;
			first.val = last.val;
			last.val = val;

			first = first.next;
			last = last.prev;
		}
	}

	public void deleteAll(){
		/*清空链表*/
		DNode<T> x = null;
		while(this.next != this){
			x = deleteAfter(this);
			x = null;
		}
	}
	
	public DNode<T> insertionSort()
	{/*递增排序*/
		DNode<T> list = new DNode<T>(),  j = null, x = null;
		DNode<T> head = this;
		
		x = head.deleteAfter(head);	
		for(; x != head; x = head.deleteAfter(head)){
			/*<= 导致不稳定排序。查找如果从前往后就不能体现插入排序的优势了*/
			j = list.prev;
			while(j != list && x.val.compareTo(j.val) < 0){
				j = j.prev;
				/*如果是数组,这里边移位arr[j+1] = arr[j]。
				 * 由此看出,只有sizeof(T)大于计算机字长时,链表形式的才更快*/
			}

			System.out.println(list.toString() + " <-- " + x.val + " at " + j.val);
			list.insertAfter(j, x);
		}
		
		return list;
	}
	
	public int search( T val){
		/*如果没有找到返回-1*/
		DNode<T> first = this.next;
		int idx = 0;
		for(; first != this; first = first.next){
			if(0 == first.val.compareTo(val))return idx;
			++idx;
		}

		System.out.printf("===xx\n"); /*这个为什么没有打出来?A: 不要这样调println(search(i));*/
		return -1;
	}
}

public class LinkedListTest{
	public static void main(String[] arg){
		/*创建链表头,节点引用*/
		DNode<Integer> head = new DNode<Integer>(), node = null, curr = null;
		int i;
		
		for(i = 0; i < 5; ++i){
			node = new DNode<Integer>(2*i);
			head.insertTail(node);
		}
		System.out.println(head.toString() );
		
		for(i = 0; i < 5; ++i){
			node = new DNode<Integer>(2*i+1);
			head.insertAfter(head, node);
		}
		System.out.println(head.toString() );
		
		i = 5;	
		node = head.indexOf(i);
		head.deleteAfter(node);
		System.out.printf("delete afert %d-th %d:\n", i, node.val);
		System.out.println(head.toString() );
		
		head.reverseList();
		System.out.println("reversed:\n" + head.toString());

		node = head.insertionSort(); 
		head = null; head = node; /*防内存泄露, 编译器会不会自动搞?*/
		System.out.println("Sorted:\n" + head.toString());
		
		i = 6;
		System.out.printf("Search %d at pos %d\n", i, head.search( i)); 
		
		head.deleteAll();
		System.out.println("deleteAll:\n" + head.toString());
		head = null;	
	}
}

/*
ludi@ubun:~/java
$ javac -encoding UTF-8 LinkedListTest.java  && java LinkedListTest  
[0, 2, 4, 6, 8, ]
[9, 7, 5, 3, 1, 0, 2, 4, 6, 8, ]
delete afert 5-th 0:
[9, 7, 5, 3, 1, 0, 4, 6, 8, ]
reversed:
[8, 6, 4, 0, 1, 3, 5, 7, 9, ]
Sorted:
[0, 1, 3, 4, 5, 6, 7, 8, 9, ]
Search 6 at pos 5
deleteAll:
[]
ludi@ubun:~/java
$ 
*/


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值