精华内容
下载资源
问答
  • 快速寻找单链表中间元素结点

    千次阅读 2014-11-26 10:36:05
    一看到这倒题目,下意识想到解决方案便是首先循环遍历链表获得链表长度Len,然后再次循环遍历链表查找Len/2处中间节点。在这种情况下,其时间复杂度两次循环决定:O(L+L/2)=O(3L/2)。 尽管这种思路也能...

    忘记什么时候做的笔试题了。记忆力差没办法。

    一看到这倒题目,下意识的想到的解决方案便是首先循环遍历链表获得链表长度Len,然后再次循环遍历链表查找Len/2处的中间节点。在这种情况下,其时间复杂度由两次循环决定:O(L+L/2)=O(3L/2)。

    尽管这种思路也能解决问题,但也许存在更好的方法。上次我们谈到利用双指针来寻找链表中倒数第N个元素结点,现在我们同样也可以利用双指针来查找中间节点:

    设置两个指针*search,*mid,初始时,都指向头结点。其中*search的移动速度为*mid的两倍。类比物理中的匀速运动,相同时间内,*search经过的结点应该是*mid结点个数的2倍,也就说,当*search结点到达链表终点时,*mid在链表中间结点处。

    下面放上代码实现:

    #include<stdlib.h>
    #include<string.h>
    #include<stdio.h>
    
    typedef int elemType;
    typedef struct Node{//定义链接节点
    	elemType element;
    	Node* next;
    }Node;
    int insertLast(Node** pNode, elemType ele);
    //1、初始化链表,未带头结点
    void init(Node** pNode){
    	*pNode = NULL;
    	printf("------>链表初始化<------\n");
    }
    
    void init_n(Node** pNode){
    	*pNode = (Node*)malloc(sizeof(Node));//产生头结点,并使pNode头指针指向头结点
    	if (!(*pNode)){
    		printf("头结点初始化空间失败\n");
    	}
    	printf("------>链表初始化<------\n");
    	(*pNode)->next = NULL;
    }
    //1、创建链表
    Node* create(Node* pHead){
    	Node* p1;//代表新节点
    	Node * p2;//代表尾节点
    	p1 = p2 = (Node*)malloc(sizeof(Node));//申请节点
    	if (p1 == NULL || p2 == NULL){
    		printf("内存空间申请失败\n");
    		exit(0);
    	}
    	memset(p1, 0, sizeof(Node));
    	printf("输入节点值(非正数结束):");
    	scanf_s("%d", &p1->element);//输入新节点
    	p1->next = NULL;
    	while (p1->element > 0){
    		if (pHead == NULL){//空节点,接入表头
    			pHead = p1;
    		}
    		else{
    			p2->next = p1;//非空表,接入尾节点
    		}
    		p2 = p1;//重新让p2做尾节点
    		p1 = (Node*)malloc(sizeof(Node));
    		if (p1 == NULL || p2 == NULL){
    			printf("内存分配失败\n");
    			exit(0);
    		}
    		memset(p1, 0, sizeof(Node));
    		printf("输入节点值(非正数结束):");
    		scanf_s("%d", &p1->element);
    		p1->next = NULL;
    
    	}
    
    	printf("链表创建成功\n");
    	return pHead;
    }
    
    
    
    
    //打印链表,不带头结点的情况
    void print(Node* pHead){
    	if (pHead == NULL){
    		printf("链表为空\n");
    	}
    	else{
    		while (pHead != NULL){
    			
    				printf("%d,", pHead->element);
    				pHead = pHead->next;
    			
    			
    		}
    		printf("\n");
    	}
    }
    
    
    //链表长度
    int size(Node* pHead){
    	int size = 0;
    	while (pHead != NULL){
    		size++;
    		pHead = pHead->next;
    	}
    	printf("链表长度%d\n", size);
    	return size;
    }
    
    //获取指定位置的元素
    elemType get(Node* pHead, int pos){
    	int i = 0;
    	if (pos < 1){
    		printf("pos值不合法\n");
    		return 0;
    	}
    	if (pHead == NULL){
    		printf("链表为空\n");
    		return 0;
    	}
    	while (pHead != NULL){
    		++i;
    		if (pos == i){
    			break;
    		}
    		pHead = pHead->next;
    	}
    	if (i < pos){
    		printf("pos值超出范围\n");
    		return 0;
    	}
    	return pHead->element;
    }
    
    
    //插入头节点
    int insertHead(Node** pNode, elemType ele){
    	Node* pInsert;
    	pInsert = (Node*)malloc(sizeof(Node));
    	pInsert->element = ele;
    	pInsert->next = *pNode;
    	*pNode = pInsert;//代表头节点
    	printf("向表头插入元素:%d\n",ele);
    	return 1;
    }
    //插入尾节点
    int insertLast(Node** pNode, elemType ele){
    	Node* pInsert;
    	Node* pHead;
    	Node* pTmp;
    
    	pHead = *pNode;
    	pTmp = pHead;
    	pInsert = (Node* )malloc(sizeof(Node));
    	memset(pInsert, 0, sizeof(Node));
    	pInsert->element = ele;
    	while (pHead->next != NULL){
    		pHead = pHead->next;
    	}
    	pHead->next = pInsert;
    	*pNode = pTmp;
    	printf("向表尾插入元素:%d\n",ele);
    		return 1;
    }
    //在指定位置插入元素
    int insertMid(Node** pNode, int pos, elemType ele){
    	Node* pHead;
    	Node* nHead;
    	pHead = *pNode;
    	Node* pInsert;
    	pInsert = (Node*)malloc(sizeof(Node));
    	memset(pInsert, 0, sizeof(Node));
    	pInsert->element = ele;	
    	int i = 0;
    	if (pNode == NULL){
    		printf("链表为空\n");
    		return 0;
    	}
    	if (pos < 1){
    		printf("pos值非法\n");
    		return 0;
    	}
    	while (pHead != NULL){
    		++i;
    		if (i == pos){
    			break;
    
    		}
    		pHead = pHead->next;
    	}
    	if (i < pos){
    		printf("pos值超出范围\n");
    		return 0;
    	}
    	
    	nHead = pHead->next;//保存后一个节点
    	pInsert->next = pHead->next;
    	pHead->next = pInsert;
    	printf("插入中间节点\n");
    	return 1;
    }
    //删除指定位置元素
    int deleteMidEle(Node** pNode, int pos){
    	Node* pHead;
    	Node* de;
    	pHead = *pNode;
    	int i = 0;
    	if (pNode == NULL){
    		printf("pos值非法");
    		return 0;
    	}
    
    	while (pHead != NULL){
    		++i;
    		if (i == (pos-1)){
    			break;
    
    		}
    		pHead = pHead->next;
    	}
    	de = pHead->next;
    	pHead->next=de->next;
    	printf("删除元素成功\n");
    	return 1;
    }
    //删除第一个节点
    int delHead(Node** pNode){
    	Node* pHead = *pNode;
    	if (pNode == NULL){
    		printf("链表为空,删除失败\n");
    		return 0;
    	}
    	if (pHead->next == NULL){//只有一个节点,设置头指针为空
    		printf("删除头节点成功\n");
    		pHead = NULL;
    		*pNode = pHead;
    		return 1;
    	}
    	pHead = pHead->next;//设置原先头节点的下一个节点为头节点
    	*pNode = pHead;
    		printf("删除头节点成功\n");
    		return 1;
    }
    //删除尾节点
    int delLast(Node** pNode){
    	Node* pHead = *pNode;
    	Node* preDel=pHead;
    	if (*pNode == NULL){
    		printf("链表为空,删除失败\n");
    		return 0;
    	}
    	while (pHead->next!= NULL){
    		preDel = pHead;
    		pHead = pHead->next;
    	}
    	printf("删除尾节点\n");
    	
    	free(pHead);
    	preDel->next = NULL;
    	return 1;
    
    }
    //一次遍历查找倒数第n个元素
    int getNodeFromBack(Node* pHead, int n, elemType *e){
    	int i = 0; 
    	Node* p = pHead;
    	while (i < n&& p->next != NULL){//查找正数第n个节点
    		i++;
    		p = p->next;
    		printf("%d---%d\n", i,p->element);
    	}
    
    	if (p->next == NULL&&i < n - 1){
    		printf("超出链表长度\n");
    		return 0;
    
    	}
    	Node* p2 = pHead;
    	while (p != NULL){//查找倒数第n个节点
    		p2 = p2->next;
    		p = p->next;
    
    	}
    	*e = p2->element;
    	printf("倒数第%d个元素是:%d\n", n, *e);
    	return 1;
    }
    //查找中间元素结点
    int getMidNode(Node* pHead, elemType *e){
    	Node* mid,*search;
    	mid = search = pHead;
    	while (search->next != NULL){
    		if (search->next->next != NULL){
    			search = search->next->next;
    			mid = mid->next;
    		}
    		else{
    			search = search->next;
    		}
    	}
    	*e = mid->element;
    	return 1;
    }
    void main(){
    	Node* pList=NULL;
    	int length = 0;
    	elemType el;
    	init(&pList);
    	pList = create(pList);
    	print(pList);
    	getMidNode(pList,&el);
    
    	system("pause");
    }

    总结:

    涉及单链表优化的问题,首先要考虑是否可以用双指针解决。

    展开全文
  • TreeNodes占用空间是普通Nodes两倍,所以只有当bin包含足够多节点时才会转成TreeNodes,而是否足够多就是TREEIFY_THRESHOLD决定的。当bin中节点数变少时,又会转成普通bin。并且我们查看源码时候发现...

    源码中的说法:

    TreeNodes占用空间是普通Nodes的两倍,所以只有当bin包含足够多的节点时才会转成TreeNodes,而是否足够多就是由TREEIFY_THRESHOLD的值决定的。当bin中节点数变少时,又会转成普通的bin。并且我们查看源码的时候发现,链表长度达到8就转成红黑树,当长度降到6就转成普通bin。

    这样就解释了为什么不是一开始就将其转换为TreeNodes,而是需要一定节点数才转为TreeNodes,说白了就是权衡,空间和时间的权衡。

    这段内容还说到:当hashCode离散性很好的时候,树型bin用到的概率非常小,因为数据均匀分布在每个bin中,几乎不会有bin中链表长度会达到阈值。但是在随机hashCode下,离散性可能会变差,然而JDK又不能阻止用户实现这种不好的hash算法,因此就可能导致不均匀的数据分布。不过理想情况下随机hashCode算法下所有bin中节点的分布频率会遵循泊松分布,我们可以看到,一个bin中链表长度达到8个元素的概率为0.00000006,几乎是不可能事件。所以,之所以选择8,不是随便决定的,而是根据概率统计决定的。由此可见,发展将近30年的Java每一项改动和优化都是非常严谨和科学的。

    也就是说:选择8因为符合泊松分布,超过8的时候,概率已经非常小了,所以我们选择8这个数字。

    另一种说法:

    红黑树的平均查找长度是log(n),如果长度为8,平均查找长度为log(8)=3,链表的平均查找长度为n/2,当长度为8时,平均查找长度为8/2=4,这才有转换成树的必要;链表长度如果是小于等于6,6/2=3,而log(6)=2.6,虽然速度也很快的,但是转化为树结构和生成树的时间并不会太短。

    展开全文
  • HashMap结构是数组加链表,容量指是数组长度。 元素放入数组哪个位置算出来HashCode 跟 1111 作与运算得出数组下标。为什么是1111,因为0000~1111共16个数,跟数组下标一致。可以说存放到哪个位置,...

    这里不讲代码,只讲思路。要稍微懂点二进制

     

    初始容量

    HashMap的结构是数组加链表,容量指的是数组长度。

    元素放入数组的哪个位置?这由算出来的HashCode 跟 1111 作与运算(&)得出数组下标。

    hashCode具体算法我也不知道

    为什么是1111,因为0000~1111共16个数,跟数组下标、容量都一致。可以说存放到哪个位置,完全由HashCode右边四位决定。

    HashMap尽可能做到元素在数组中均匀分布。

    如果容量是10,HashCode就要跟1001做与运算,结果二进制下HashCode的右边四位数如果是1001,1011,1101,1111,算出来结果都是1xx1 & 1001 = 1001,都会落在数组第9位。有些结果也永远不会出现,如1111 ,即数组15位永远不会有东西。

     

    扩容

    扩容时是翻倍,其实是16 变成32,二进制中对应11111,算法跟以上类似。

    展开全文
  • 你必须知道495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    1.23 能否声明和传入数组大小一致局部数组,或者其他参数指定大小参数数组? 1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,为什么sizeof取不到数组大小? 声明问题 1.25 函数只...
  • 《你必须知道495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    1.23 能否声明和传入数组大小一致局部数组,或者其他参数指定大小参数数组? 13 1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,为什么sizeof取不到数组大小? 13 声明问题 14 ...
  • 1.23 能否声明和传入数组大小一致局部数组,或者其他参数指定大小参数数组? 13 1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,为什么sizeof取不到数组大小? 13 声明问题 14 ...
  • 1.23 能否声明和传入数组大小一致局部数组,或者其他参数指定大小参数数组?  1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,为什么sizeof取不到数组大小?  声明问题  1.25 ...
  •  数组大小 1.23 能否声明和传入数组大小一致局部数组,或者其他参数指定大小参数数组? 1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,为什么sizeof取不到数组大小? 声明问题 ...
  • 1.23 能否声明和传入数组大小一致局部数组,或者其他参数指定大小参数数组? 42 1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,为什么sizeof取不到数组大小? 42 声明问题 43 1.25...
  • 1.23 能否声明和传入数组大小一致局部数组,或者其他参数指定大小参数数组? 42 1.24 我在一个文件中定义了一个extern数组,然后在另一个文件中使用,为什么sizeof取不到数组大小? 42 声明问题 43 1.25...
  • 数据结构

    2021-04-03 15:17:44
    而不管是什么数据结构,我们在选择时候往往是时间复杂度来决定的。 本篇从如何选择数据结构角度,来介绍各个数据结构。 数据结构基石 数组结构 和 链表结构, 由于数组长度固定,插入和删除需要移动,满了...

    数据结构

    最初接触数据结构,往往从存储结构去认识去学习。
    而不管是什么数据结构,我们在选择的时候往往是由时间复杂度来决定的。

    本篇从如何选择数据结构的角度,来介绍各个数据结构。

    数据结构的基石

    数组结构 和 链表结构,
    由于数组长度固定,插入和删除需要移动,满了需要扩容。时间复杂度对比如下:

    顺序插入 随机插入 随机查询 删除 扩容
    数组 1 n 1 n n
    链表 1 n n 1 0

    所以数组更适合做读操作,链表更适合处理修改操作。

    此外 从内存的角度思考:

    数组在初始化时,开辟相应长度的内存空间。
    链表则是动态的申请内存。

    所以

    1. 数组长度内的增删操作,快于链表的增删。
    2. 链表内存利用率100%,数组的要小于等于100%

    数组的应用:

    栈的实现

    栈特性,后入先出。 所以只会在末尾处新增和删除。 数组和链表都可以实现。
    数组的实现方式:

    • 新建一个数组,入栈放进数组,出栈从当前存储数量-1的位置删除。
      需要一个额外空间保存当前栈内元素的数量。
      优点:
      1. 提前申请一块固定大小的数组空间,后续不用申请。
    • 链表的实现方式:
      入栈作为头结点, 出栈移除头结点,下一节点作为头。
      缺点:
      1. 链表的内存空间是动态获取的。
      2. 同规模的链表比数组占有空间多。

    jdk中Stack类的实现,是继承自 Vector类
    stack类图

    链表的应用

    队列的实现

    队列特性,先入先出。 假设出口A,即队列的头部,入口B,队列的尾部。

    jdk对于Queue的实现提供了数组和链表两种方式:

    数组方式:

    ArrayQueue
    基本思想: (下标增大为前进,下标减小为后退)

    1. AB初始索引=0;
    2. 头部追加,A向后退一位,数组越界,则跳到数组尾部继续后退。
    3. 尾部追加,B向前进一位。
    4. 当AB相遇,说明数组已经存满。可以进行扩容。扩容过程大致为 在AB间插入原数组长度。
    5. 出队时,A向前进一位。遇到B说明队列为空。数组越界则跳到数组头部继续前进。

    数据分布图:

    (没找到合适的作图工具,先欠着)自行脑补

    类图:
    在这里插入图片描述
    优点:

    • 不用动态申请释放内存。入队出队速度略快于链表。

    缺点:

    • 存在扩容,扩容时时间复杂度为n。
    • 内存利用率低于链表。

    链表实现

    jdk中链表实现示例:
    LinkedList
    基本思想:

    1. 双向链表
    2. 保存头尾双节点
    3. 支持头插,尾插
    4. pop方法 从头节点出,add方法从尾节点入。

    链表方式比较常规,不做详细介绍。

    类图:
    在这里插入图片描述

    散列表(哈希表)

    实现了O1的快速查找。
    每当遇到一个要求时间复杂度为O1的算法时,第一想到的就是数组或该结构。

    基本结构:

    数组+链表。

    基本思想:

    散列思想依赖于 java中通过hashCode()和equals()方法标识唯一。

    在java中,如果某个对象A的hashCode()返回值等于另一个对象B。且 A.equals(B) == true; 则AB标识唯一。 例如:新旧两个身份证,代表同一个人。

    与此思想相关的还有不变性等设计思想(为何String设计成final)。有兴趣可以拓展看一下。

    1. 通过hash值对数组长度取模,找到该key对应的数组位置
    2. 如果数组位置为null。创建一个链表,保存此key
    3. 如果数组位置有值,判断equals,相同覆盖,否则加入链表
      此时加入链表,在jdk,hashMap中,1.7与1.8实现不同,后面文章会提到。

    散列表,除了在时间复杂度上的优势以外,也是常见的分治算法思想

    比如:求1000000个数中,出现频率最高的数,可以对数求hash,分配到不同的桶中,求各桶出现最多的数以及次数,然后合并各桶结果。

    也是被用来处理并发问题的好结构

    jdk1.8版本的concuurentHashMap,基于散列表结构,来降低锁的粒度 和 完成并发场景帮助扩容(helpTransfer方法)

    树结构是生活场景中最常见的结构,比如:书的目录,电脑的文件结构,部门的组织架构等等。

    常规的树结构中,每个节点可以有多个子节点。

    节点结构可以表示为:
    Node{
    	int val;
    	List<Node> childNodeList;
    }
    

    数学上的树更多为二叉树。

    二叉树,顾名思义每个节点至多有两个子节点

    所有的二叉树,都可以用数组来存储。
    在这里插入图片描述

    上图解释:
    空置0下标,从1开始存储树的根节点,则有如下规律

    1. 左子节点 = 父节点下标 * 2
    2. 右子节点 = 父节点下标 * 2 + 1
    3. 父节点 = 当前节点 / 2
    4. 当子节点为空时, 对于下标位置存储null
    5. 数组的长度 = 对应的完全二叉树的节点数量 = 2的树深度次方。

    二叉搜索树

    在二叉树的定义上,加了新的性质:

    每一个节点的值,都要大于它的左子节点,并且小于他的右子节点。

    二叉搜索树最大的应用: 二分查找

    二分查找
    因为要查找的值,要么在当前节点左边,要么在当前节点右边,所以每次查询能够去掉一半的选择,
    所以:二叉查找树的平均时间复杂度 为 logN
    但是
    最终的查询次数,取决于节点的分布情况,当所有的节点都是右节点或左节点,树就退化成了链表,
    所以:此时的实际时间复杂度为 n
    为了解决这个问题,引入了平衡二叉搜索树的概念。

    平衡二叉搜索树

    在二叉搜索树的定义上,加了新的性质,平衡性。
    平衡二叉树的查询时间复杂度logN。

    平衡性,简单来说,就是各节点在根结点的左右两边的分布是接近的(非准确答案)

    在此性质上,实际的查询时间复杂度分布,就接近于平均时间复杂度了。

    目前常见的平衡二叉搜索树有: AVL树 和 红黑树。
    他们对平衡性有不同的定义,因此有不同的平衡效果,以及各自的优势。
    链接: https://www.cnblogs.com/ajianbeyourself/p/11173851.html

    平衡二叉搜索树,分为两部分:

    1. 使用一些定义特性来保证其平衡性
    2. 提供了平衡性被破坏时的,恢复平衡的算法。

    比如:

    1. 红黑树的5个性质,定义了其是 非高度平衡的;
    2. 红黑树完成自平衡的最小单元是 子父爷
    3. 在子父爷场景内, 所有的破坏平衡性操作,都可以通过左旋、右旋、内旋、外旋的基本操作回归平衡

    跳表 (研究不深,提供思路,勿轻信)

    跳表,是基于链表结构,对链表的查询时间复杂度n,做了优化,理想时间复杂度为logN
    在jdk中对于跳表结构应用的比较少。

    为什么呢? 以下为猜测:
    jvm中,数据结构和数据是分开存放的。
    例如:一个Student数组,开辟一块数组空间,空间内存放的是Student对象的地址。 而具体的Student对象是存放在其他内存区域的。
    所以在这个场景里,底层是数组的二叉树存储方式,时间复杂度和跳表一致。二叉树数组在大多数场景可以替代跳表。

    那跳表在哪里使用呢?

    跳表的应用,一般体现在中间件的存储上。
    例如: redis的Zset结构。 es的索引结构。
    这可能是因为,对象直接放在了存储结构里。
    还是用数组来举例, 开辟了一个数组,那么对象的存储,就在这数组的一个个空间里。
    由于对象的占用内存空间不固定
    所以在这种场景,动态申请内存释放内存是必要的,因此链表比数组更合适,从而跳表比二叉树更合适。


    终极问题: 那为什么不使用B+树呢? B+树的叶子节点也是链表节点啊?
    外部链接:https://blog.csdn.net/z69183787/article/details/89470896

    jdk中
    有ConcurrentSkipListMap (没用过)
    跳表结构:
    在这里插入图片描述
    跳表创建索引的随机算法,具体含义是:

    // 理论来讲,一级索引中元素个数应该占原始数据的 50%,二级索引中元素个数占 25%,三级索引12.5% ,一直到最顶层。
    // 因为这里每一层的晋升概率是 50%。对于每一个新插入的节点,都需要调用 randomLevel 生成一个合理的层数。
    // 该 randomLevel 方法会随机生成 1~MAX_LEVEL 之间的数,且 :
    // 50%的概率返回 1
    // 25%的概率返回 2
    // 12.5%的概率返回 3 …

    所以,为什么使用随机算法来确定是否建立索引,也就比较好理解了。

    展开全文
  •  SessionBean: Stateless Session Bean 生命周期是容器决定的,当客户机发出请求要建立一个Bean实例时,EJB容器不一定要创建一个新Bean实例供客户机调用,而是随便找一个现有实例提供给客户机。...
  • 你必须知道495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    1.2 64 位机上64 位类型是什么? . . . . . . . . . . . . . . . . 1 1.3 怎样定义和声明全局变量和函数最好? . . . . . . . . . . . . . . . 2 1.4 extern 在函数声明中是什么意思? . . . . . . . . . . . ...
  • 17、堆栈溢出一般是由什么原因导致? 答: 没有回收垃圾资源。 18、什么是预编译?何时需要预编译? 答: (1)总是使用不经常改动大型代码体。 (2)程序由多个模块组成,所有模块都使用一组标准包含文件和相同...
  • 空间,这些内容决定了变量在程序哪些部分是可见。 第10章:对象和类 类是用户定义类型,对象(如变量)是类实例。本章介绍面向对象编程和类设计。对象声明描述是存 储在对象中信息以及可对对象执行...
  • 空间,这些内容决定了变量在程序哪些部分是可见。 第10章:对象和类 类是用户定义类型,对象(如变量)是类实例。本章介绍面向对象编程和类设计。对象声明描述是存 储在对象中信息以及可对对象执行...
  • 空间,这些内容决定了变量在程序哪些部分是可见。 第10章:对象和类 类是用户定义类型,对象(如变量)是类实例。本章介绍面向对象编程和类设计。对象声明描述是存 储在对象中信息以及可对对象执行...
  • 空间,这些内容决定了变量在程序哪些部分是可见。 第10章:对象和类 类是用户定义类型,对象(如变量)是类实例。本章介绍面向对象编程和类设计。对象声明描述是存 储在对象中信息以及可对对象执行...
  • JAVA面试题最全集

    2010-03-13 13:09:10
    如何获得数组的长度? 46.访问修饰符“public/private/protected/缺省的修饰符”的使用 47.用关键字final修饰一个类或者方法时,有何意义? 48.掌握类和对象的概念,掌握面向对象编程的本质 49.静态变量和静态...
  • o 2.2 64 位机上 64 位类型是什么? o 2.3 怎样定义和声明全局变量和函数最好? o 2.4 extern 在函数声明中是什么意思? o 2.5 关键字 auto 到底有什么用途? o 2.6 我似乎不能成功定义一个链表。我试过 ...
  • 如果能熟练使用链表或树结构也会有一些帮助,但不是必须。  对于只懂得C但不懂得C++读者来说,需要掌握面向对象编程理念。本书中定义了许多有用类(如网格、场景、相机和纹理等类),并且说明了这些类为...
  • java 面试题 总结

    2009-09-16 08:45:34
    通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项前后项即可,所以插入速度较快。 8、EJB是基于哪些技术实现?并说出Session...
  • C++MFC教程

    热门讨论 2013-05-21 13:37:15
    CStringArray:用来表示可变长度的字符串数组。数组中每一个元素为CString对象实例。下面介绍几个成员函数: Add 增加CString RemoveAt 删除指定位置CString对象 RemoveAll 删除数组中所有CString对象 GetAt ...

空空如也

空空如也

1 2
收藏数 37
精华内容 14
关键字:

链表的长度由什么决定