哪些学校使用了《数据据结构》 顾泽元 幼儿园教材有哪些

及旗下全部分类
打开微信扫一扫,关注圣才:
sc100xuexi
认证官方微博
认证官方微博
严蔚敏《数据结构》(C语言版)网授精讲班【教材精讲+考研真题串讲】
根据您的学习记录,系统已自动为您打开了上次播放的章节,如观看其他章节,请重新选择。
选择课程/章节播放
&在手机上观看
用圣才学霸或微信扫一扫,在手机上观看该视频课程。
摇摇手机,摇出本视频课程学友,交流学习!在学习中泡妞,在泡妞中学习。
说明:本圣才课程共包括30个高清视频(共36课时)。购买后,圣才课程里的所有视频、3D电子书(题库)及资料均可使用。
◇ 班型简介
本课程由资深计算机类辅导教师耿佳老师独家讲授,全面讲解教材的重点、难点、考点,教会学员理解与掌握该教材中的基本概念、基本原理和基本方法,并结合名校考研真题和典型试题引导学员掌握答题的思路与方法,进一步提升应试能力。同时从不同侧面把握应试考点,再针对性地进行重点讲解,缩减考试范围,更准确地把握考试的方向和思路。
网授精讲班以大屏高清网络视频为载体,开启全新一代教学模式,给学员带来视觉上的震撼!通过授课视频和课程讲义的完美结合,为学员打造了一个最佳的视听学习空间。学员可以在有效期内随时随地通过互联网学习该课程,有效期为自报班之日起一年,在此期间可多次学习。
◇ 授课时间、地点、师资、课时、收费
&授课时间:随报随学
&授课地点:全国(有上网条件即可)
&授课师资:耿佳
&授课课时:36课时
&授课收费:300元
◇ 授课教师
圣才教育特聘清华大学、北京大学、华中科技大学、武汉大学、南开大学等名校长期从事计算机类授课的优秀教师担任顾问老师,这些教师授课经验丰富,教学方法独特精湛,尤其考前应试技巧,独特实用;善于将理论与现实联系起来,深入浅出,精确把握计算机类的要点及命题角度,深受业界一致好评。
本课程的授课教师简介如下:
,讲师,北京交通大学中国产业安全研究中心博士后,信息管理方向。硕士毕业于首都师范大学信息工程学院,在高校及职业培训机构讲授计算机课程,主讲课程多为计算机考研考博课程,如数据结构,计算机网络,人工智能,C语言程序设计等。深受学生喜爱,了解学生学习心理,具备教育学专业知识,所教学生成绩优异。
授课特点:教学思路清晰,内容条理性强,重点难点突出,语言清晰流畅。
◇ 课程特色
本课程特色突出,集中体现在以下四个方面:
1.独家师资优:独家资深计算机类考试实力名师打造
本课程由独家资深计算机类实力派辅导名师耿佳老师倾力打造。耿佳老师理论功底雄厚、教学严谨、脉络清晰,注重理论知识内容的讲解,同时更多地从应试的角度予以讲述,精选解析名校历年考研真题,引导学员掌握答题思路与方法,完整讲授了全部内容。
2.应试效果好:名校考研真题命题规律与方法分析
为满足学员的考研考博应试需求,耿佳老师在讲述过程中完全站在学员需求的角度,对重点、难点进行详细的讲述,做到有的放矢,着重从掌握知识与分析解题思路的角度全面讲解考研考博所要求的相关内容,以达到夯实基础、全面掌握课程内容的效果。
3.知识拓展宽:提纲挈领、系统阐述计算机学科
考虑到计算机类考研考博真题难度为中级水平,部分名校计算机类考研考博真题难度甚至为中级偏高级,耿佳老师在讲述该教材的过程中旁征博引,适当地参考了其他相关教材,以充实课程内容。
4.联系现实紧:结合当前形势,解说理论
为提高学员学习兴趣和符合应试需要,本课程在讲述过程中特别注重结合实践和当前热点问题阐述计算机类理论,注重计算机类理论的现实解说力分析。
◇ 课程结构
本课程的具体目录如下:
严蔚敏《数据结构》(C语言版)
  第1章 绪 论
  第2章 线性表
  第3章 栈与队列
  第4章 串
  第5章 数组和广义表
  第6章 树和二叉树
  第7章 图
  第8章 动态存储管理
  第9章 查 找
  第10章 内部排序
  第11章 文件与外部排序
注:学员可下载电子版讲义打印学习!
◇ 适用对象
严蔚敏《数据结构》(C语言版)是我国众多院校采用的计算机类优秀教材,也被众多院校指定为&计算机类&专业考研考博参考书目。本课程特别适用于各大院校学习严蔚敏《数据结构》(C语言版)的师生,以及在高校硕士和博士研究生入学考试中参加计算机类考试科目的考生使用。
1.网络课程师资力量强,辅导经验丰富
圣才教育的网络课程特聘长期从事考试辅导培训的名校知名教授专家和一线授课老师亲自打造。这些辅导老师均有丰富的辅导经验,对各类考试和经典教材把握精准,应试技巧独特实用;善于将理论与现实联系起来,深入浅出,精确把握各类考试和经典教材的要点及考试命题角度。我们的师资力量,
2.拥有强大的图书(e书、题库)编辑团队
圣才教育积淀十二年考试辅导资料与经验,拥有强大的图书(e书、题库)编辑团队。针对各种考试和经典教材推出的多媒体题库和e书重点突出,考点命中率高。其中,圣才题库涵盖市面上所有试题,包括历年真题、教材课后习题、高校题库等,题库中部分真题反复被考试选作真题,最多的试题已经被采用为真题十几次。我们的全部e书(含题库),
此外,我们是全国惟一一家编写各类考试辅导系列和国内外经典教材习题详解系列等配套辅导书籍的培训机构,并长期占据考试辅导资料的绝对领导者地位,受到广大考生的高度评价。
更多配套视频课程、3D电子书(题库),请浏览。
24离你最近 武汉大学
天灰灰,心沉沉,谁来陪我上自习
发表学友说
上传图片(0/10)IBM Bluemix
点击按钮,开始云上的开发!
developerWorks 社区
本文是讨论多线程结构的两篇系列文章的第二篇,介绍关于实现基于互斥锁的并发链表的设计方法,讨论如何设计不使用互斥锁的并发数据结构。
, 独立作家
Arpan Sen 是致力于电子设计自动化行业的软件开发首席工程师。他使用各种 UNIX 版本(包括 Solaris、SunOS、HP-UX 和 IRIX)以及 Linux 和 Microsoft Windows 已经多年。他热衷于各种软件性能优化技术、图论和并行计算。Arpan 获得了软件系统硕士学位。
简介本文是本系列的最后一篇,讨论两个主题:关于实现基于互斥锁的并发链表的设计方法和设计不使用互斥锁的并发数据结构。对于后一个主题,我选择实现一个并发堆栈并解释设计这种数据结构涉及的一些问题。用 C++ 设计独立于平台的不使用互斥锁的数据结构目前还不可行,所以我选用 GCC version 4.3.4 作为编译器并在代码中使用 GCC 特有的 __sync_* 函数。如果您是 WIndows® C++ 开发人员,可以考虑使用 Interlocked* 系列函数实现相似的功能。
并发单向链表的设计方法
给出最基本的并发单向链表接口。是不是缺少什么东西?
清单 1. 并发单向链表接口template &typename T&
class SList {
typedef struct Node {
Node(T& data) : value(data), next(NULL) { }
pthread_mutex_t _
Node *head, *
void push_back(T& value);
void insert_after(T& previous, T& value); // insert data after previous
void remove(const T& value);
bool find(const T& value);
// return true on success
}; 给出 push_back 方法定义。
清单 2. 把数据添加到并发链表中void SList&T&::push_back(T& data)
pthread_mutex_lock(&_lock);
if (head == NULL) {
head = new Node(data);
tail-&next = new Node(data);
tail = tail-&
pthread_mutex_unlock(&_lock);
}现在,假设一个线程试图通过调用 push_back 把 n 个整数连续地添加到这个链表中。这个接口本身要求获取并释放互斥锁 n 次,即使在第一次获取锁之前已经知道要插入的所有数据。更好的做法是定义另一个方法,它接收一系列整数,只获取并释放互斥锁一次。 给出方法定义。
清单 3. 在链表中插入数据的更好方法void SList&T&::push_back(T* data, int count) // or use C++ iterators
Node *begin = new Node(data[0]);
Node *temp =
for (int i=1; i& ++i) {
temp-&next = new Node(data[i]);
temp = temp-&
pthread_mutex_lock(&_lock);
if (head == NULL) {
tail-&next =
pthread_mutex_unlock(&_lock);
}优化搜索元素现在,我们来优化链表中的搜索元素 — 即 find 方法。下面是几种可能出现的情况:
当一些线程正在迭代链表时,出现插入或删除请求。
当一些线程正在迭代链表时,出现迭代请求。
当一些线程正在插入或删除数据时,出现迭代请求。
显然,应该能够同时处理多个迭代请求。如果系统中的插入/删除操作很少,主要活动是搜索,那么基于单一锁的方法性能会很差。在这种情况下,应该考虑使用读写锁,即 pthread_rwlock_t。在本文的示例中,将在 SList 中使用 pthread_rwlock_t 而不是 pthread_mutex_t。这么做就允许多个线程同时搜索链表。插入和删除操作仍然会锁住整个链表,这是合适的。 给出使用 pthread_rwlock_t 的链表实现。
清单 4. 使用读写锁的并发单向链表template &typename T&
class SList {
typedef struct Node {
// … same as before
pthread_rwlock_t _ // Not pthread_mutex_t any more!
Node *head, *
// … other API remain as-is
) : head(NULL), tail(NULL) {
pthread_rwlock_init(&_rwlock, NULL);
pthread_rwlock_destroy(&_rwlock);
// … now cleanup nodes
}; 给出链表搜索代码。清单 5. 使用读写锁搜索链表bool SList&T&::find(const T& value)
pthread_rwlock_rdlock (&_rwlock);
Node* temp =
while (temp) {
if (temp-&value == data) {
temp = temp-&
pthread_rwlock_unlock(&_rwlock);
} 给出使用读写锁的 push_back 方法。
清单 6. 使用读写锁在并发单向链表中添加数据void SList&T&::push_back(T& data)
pthread_setschedprio(pthread_self( ), SCHED_FIFO);
pthread_rwlock_wrlock(&_rwlock);
// … All the code here is same as Listing 2
pthread_rwlock_unlock(&_rwlock);
}我们来分析一下。这里使用两个锁定函数调用(pthread_rwlock_rdlock 和 pthread_rwlock_wrlock)管理同步,使用 pthread_setschedprio 调用设置写线程的优先级。如果没有写线程在这个锁上阻塞(换句话说,没有插入/删除请求),那么多个请求链表搜索的读线程可以同时操作,因为在这种情况下一个读线程不会阻塞另一个读线程。如果有写线程等待这个锁,当然不允许新的读线程获得锁,写线程等待,到现有的读线程完成操作时写线程开始操作。如果不按这种方式使用 pthread_setschedprio 设置写线程的优先级,根据读写锁的性质,很容易看出写线程可能会饿死。
下面是对于这种方式要记住的几点:如果超过了最大读锁数量(由实现定义),pthread_rwlock_rdlock 可能会失败。
如果有 n 个并发的读锁,一定要调用 pthread_rwlock_unlock n 次。
允许并发插入应该了解的最后一个方法是 insert_after。同样,预期的使用模式要求调整数据结构的设计。如果一个应用程序使用前面提供的链表,它执行的插入和搜索操作数量差不多相同,但是删除操作很少,那么在插入期间锁住整个链表是不合适的。在这种情况下,最好允许在链表中的分离点(disjoint point)上执行并发插入,同样使用基于读写锁的方式。下面是构造链表的方法:
在两个级别上执行锁定(见 ):链表有一个读写锁,各个节点包含一个互斥锁。如果想节省空间,可以考虑共享互斥锁 — 可以维护节点与互斥锁的映射。
在插入期间,写线程在链表上建立读锁,然后继续处理。在插入数据之前,锁住要在其后添加新数据的节点,插入之后释放此节点,然后释放读写锁。
删除操作在链表上建立写锁。不需要获得与节点相关的锁。
与前面一样,可以并发地执行搜索。清单 7. 使用两级锁定的并发单向链表template &typename T&
class SList {
typedef struct Node {
pthread_mutex_
Node(T& data) : value(data), next(NULL) {
pthread_mutex_init(&lock, NULL);
~Node( ) {
pthread_mutex_destroy(&lock);
pthread_rwlock_t _ // 2 level locking
Node *head, *
// … all external API remain as-is
}; 给出在链表中插入数据的代码。清单 8. 使用双重锁定在链表中插入数据void SList&T&:: insert_after(T& previous, T& value)
pthread_rwlock_rdlock (&_rwlock);
Node* temp =
while (temp) {
if (temp-&value == previous) {
temp = temp-&
Node* newNode = new Node(value);
pthread_mutex_lock(&temp-&lock);
newNode-&next = temp-&
temp-&next = newN
pthread_mutex_unlock(&temp-&lock);
pthread_rwlock_unlock(&_rwlock);
}基于互斥锁的方法的问题到目前为止,都是在数据结构中使用一个或多个互斥锁管理同步。但是,这种方法并非没有问题。请考虑以下情况:
等待互斥锁会消耗宝贵的时间 — 有时候是很多时间。这种延迟会损害系统的可伸缩性。
低优先级的线程可以获得互斥锁,因此阻碍需要同一互斥锁的高优先级线程。这个问题称为优先级倒置(priority inversion ) (更多信息见
中的链接)。
可能因为分配的时间片结束,持有互斥锁的线程被取消调度。这对于等待同一互斥锁的其他线程有不利影响,因为等待时间现在会更长。这个问题称为锁护送(lock convoying)(更多信息见
中的链接)。
互斥锁的问题还不只这些。最近,出现了一些不使用互斥锁的解决方案。话虽如此,尽管使用互斥锁需要谨慎,但是如果希望提高性能,肯定应该研究互斥锁。
比较并交换指令在研究不使用互斥锁的解决方案之前,先讨论一下从 80486 开始在所有 Intel® 处理器上都支持的 CMPXCHG 汇编指令。 从概念角度说明这个指令的作用。
清单 9. 比较并交换指令的行为int compare_and_swap ( int *memory_location, int expected_value, int new_value)
int old_value = *memory_
if (old_value == expected_value)
*memory_location = new_
return old_
}这里发生的操作是:指令检查一个内存位置是否包含预期的值;如果是这样,就把新的值复制到这个位置。 提供汇编语言伪代码。
清单 10. 比较并交换指令的汇编语言伪代码
CMPXCHG OP1, OP2
if ({AL or AX or EAX} = OP1)
zero = 1Set the zero flag in the flag register
zero := 0Clear the zero flag in the flag register
{AL or AX or EAX}= OP1CPU 根据操作数的宽度(8、16 或 32)选择 AL、AX 或 EAX 寄存器。如果 AL/AX/EAX 寄存器的内容与操作数 1 的内容匹配,就把操作数 2 的内容复制到操作数 1;否则,用操作数 2 的值更新 AL/AX/EAX 寄存器。Intel Pentium® 64 位处理器有相似的指令 CMPXCHG8B,它支持 64 位的比较并交换。注意,CMPXCHG 指令是原子性的,这意味着在这个指令结束之前没有可见的中间状态。它要么完整地执行,要么根本没有开始。在其他平台上有等效的指令,例如 Motorola MC68030 处理器的 compare and swap (CAS) 指令有相似的语义。
我们为什么对 CMPXCHG 感兴趣?这意味着要使用汇编语言编写代码吗?
需要了解 CMPXCHG 和 CMPXCHG8B 等相关指令是因为它们构成了无锁解决方案的核心。但是,不必使用汇编语言编写代码。GCC (GNU Compiler Collection,4.1 和更高版本)提供几个原子性的内置函数(见 ),可以使用它们为 x86 和 x86-64 平台实现 CAS 操作。实现这一支持不需要包含头文件。在本文中,我们要在无锁数据结构的实现中使用 GCC 内置函数。看一下这些内置函数:
bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval, type newval, ...)__sync_bool_compare_and_swap 内置函数比较 oldval 和 *ptr。如果它们匹配,就把 newval 复制到 *ptr。如果 oldval 和 *ptr 匹配,返回值是 True,否则是 False。__sync_val_compare_and_swap 内置函数的行为是相似的,只是它总是返回旧值。 提供一个使用示例。
清单 11. GCC CAS 内置函数的使用示例#include &iostream&
int main()
bool lock(false);
bool old_value = __sync_val_compare_and_swap( &lock, false, true);
cout && lock && // prints 0x1
cout && old_value && // prints 0x0
}设计无锁并发堆栈既然了解了 CAS,现在就来设计一个并发堆栈。这个堆栈没有锁;这种无锁的并发数据结构也称为非阻塞数据结构。 给出代码接口。
清单 12. 基于链表的非阻塞堆栈实现
template &typename T&
class Stack {
typedef struct Node {
Node(const T& d) : data(d), next(0) { }
Stack( ) : top(0) { }
void push(const T& data);
T pop( ) throw (…);
}; 给出压入操作的定义。清单 13. 在非阻塞堆栈中压入数据void Stack&T&::push(const T& data)
Node *n = new Node(data);
while (1) {
if (__sync_bool_compare_and_swap(&top, n-&next, n)) { // CAS
}压入(Push)操作做了什么?从单一线程的角度来看,创建了一个新节点,它的 next 指针指向堆栈的顶部。接下来,调用 CAS 内置函数,把新的节点复制到 top 位置。
从多个线程的角度来看,完全可能有两个或更多线程同时试图把数据压入堆栈。假设线程 A 试图把 20 压入堆栈,线程 B 试图压入 30,而线程 A 先获得了时间片。但是,在 n-&next = top 指令结束之后,调度程序暂停了线程 A。现在,线程 B 获得了时间片(它很幸运),它能够完成 CAS,把 30 压入堆栈后结束。接下来,线程 A 恢复执行,显然对于这个线程 *top 和 n-&next 不匹配,因为线程 B 修改了 top 位置的内容。因此,代码回到循环的开头,指向正确的 top 指针(线程 B 修改后的),调用 CAS,把 20 压入堆栈后结束。整个过程没有使用任何锁。
弹出操作 给出从堆栈弹出数据的代码。清单 14. 从非阻塞堆栈弹出数据 T Stack&T&::pop( )
if (top == NULL)
throw std::string(“Cannot pop from empty stack”);
while (1) {
Node* next = top-&
if (__sync_bool_compare_and_swap(&top, top, next)) { // CAS
return top-&
}用与 push 相似的代码定义弹出操作语义。堆栈的顶存储在 result 中,使用 CAS 把 top 位置更新为 top-&next 并返回适当的数据。如果恰在执行 CAS 之前线程失去执行权,那么在线程恢复执行之后,CAS 会失败,继续循环,直到有有效的数据可用为止。
结果好就一切都好不幸的是,这种堆栈弹出实现有问题 — 包括明显的问题和不太明显的问题。明显的问题是 NULL 检查必须放在 while 循环中。如果线程 P 和线程 Q 都试图从只剩一个元素的堆栈弹出数据,而线程 P 恰在执行 CAS 之前失去执行权,那么当它重新获得执行权时,堆栈中已经没有可弹出的数据了。因为 top 是 NULL,访问 &top 肯定会导致崩溃 — 这显然是可以避免的 bug。这个问题也突显了并发数据结构的基本设计原则之一:决不要假设任何代码会连续执行。
给出解决了此问题的代码。清单 15. 从非阻塞堆栈弹出数据T Stack&T&::pop( )
while (1) {
if (top == NULL)
throw std::string(“Cannot pop from empty stack”);
Node* next = top-&
if (top && __sync_bool_compare_and_swap(&top, top, next)) { // CAS
return top-&
}下一个问题比较复杂,但是如果您了解内存管理程序的工作方式(更多信息见
中的链接),应该不太难理解。 展示这个问题。
清单 16. 内存的回收利用会导致 CAS 出现严重的问题
T* ptr1 = new T(8, 18);
T* old = ptr1;
// .. do stuff with ptr1
delete ptr1;
T* ptr2 = new T(0, 1);
// We can't guarantee that the operating system will not recycle memory
// Custom memory managers recycle memory often
if (old1 == ptr2) {
}在此代码中,无法保证 old 和 ptr2 有不同的值。根据操作系统和定制的应用程序内存管理系统的具体情况,完全可能回收利用已删除的内存 — 也就是说,删除的内存放在应用程序专用的池中,可在需要时重用,而不返回给系统。这显然会改进性能,因为不需要通过系统调用请求更多内存。尽管在一般情况下这是有利的,但是对于非阻塞堆栈不好。现在我们来看看这是为什么。
假设有两个线程 — A 和 B。A 调用 pop 并恰在执行 CAS 之前失去执行权。然后 B 调用 pop ,然后压入数据,数据的一部分来自从前面的弹出操作回收的内存。 给出伪代码。
清单 17. 序列图Thread A tries to pop
Stack Contents: 5 10 14 9 100 2
result = pointer to node containing 5
Thread A now de-scheduled
Thread B gains control
Stack Contents: 5 10 14 9 100 2
Thread B pops 5
Thread B pushes 8 16 24 of which 8 was from the same memory that earlier stored 5
Stack Contents: 8 16 24 10 14 9 100 2
Thread A gains control
At this time, result is still a valid pointer and *result = 8
But next points to 10, skipping 16 and 24!!!纠正方法相当简单:不存储下一个节点。 给出代码。
清单 18. 从非阻塞堆栈弹出数据T Stack&T&::pop( )
while (1) {
Node* result =
if (result == NULL)
throw std::string(“Cannot pop from empty stack”);
if (top && __sync_bool_compare_and_swap(&top, result, result-&next)) { // CAS
return top-&
}这样,即使线程 B 在线程 A 试图弹出数据的同时修改了堆栈顶,也可以确保不会跳过堆栈中的元素。
结束语本系列讨论了如何设计支持并发访问的数据结构。您已经看到,设计可以基于互斥锁,也可以是无锁的。无论采用哪种方式,要考虑的问题不仅仅是这些数据结构的基本功能 — 具体来说,必须一直记住线程会争夺执行权,要考虑线程重新执行时如何恢复操作。目前,解决方案(尤其是无锁解决方案)与平台/编译器紧密相关。请研究用于实现线程和锁的 Boost 库,阅读 John Valois 关于无锁链表的文章(见
中的链接)。C++0x 标准提供了 std::thread 类,但是目前大多数编译器对它的支持很有限,甚至不支持它。
MSDN 提供关于
的更多信息。
阅读 Cambridge University 的文章 。
阅读 John Valois 的文章 。
阅读 (Arpan Sen 和 Rahul Kumar Kardam,developerWorks,2008 年 2 月)。
:developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。:访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。:AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。:在这里你可以下载到可以运行在 AIX 或者是 UNIX 系统上的 IBM 服务器软件以及工具,让您可以提前免费试用他们的强大功能。:本杂志的内容更加关注于趋势和企业级架构应用方面的内容,同时对于新兴的技术、产品、应用方式等也有很深入的探讨。IBM Systems Magazine 的内容都是由十分资深的业内人士撰写的,包括 IBM 的合作伙伴、IBM 的主机工程师以及高级管理人员。所以,从这些内容中,您可以了解到更高层次的应用理念,让您在选择和应用 IBM 系统时有一个更好的认识。:浏览关于这些和其他技术主题的图书。
进一步了解并下载 。
加入 。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。
参与 AIX 和 UNIX 论坛:
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
IBM PureSystems(TM) 系列解决方案是一个专家集成系统
通过学习路线图系统掌握软件开发技能
软件下载、试用版及云计算
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=AIX and UNIXArticleID=715355ArticleTitle=用于并行计算的多线程数据结构,第 2 部分: 设计不使用互斥锁的并发数据结构publish-date=本人济南大学,2012级计算机科学与技术专业的大学生。诚心求,顾泽元版的,要有解题过程,尽量详尽完整。最好是Word版,方便打印。或者自己做的,用手机拍成高清图片也可以。要是答案书扫描成的电子文档就再好不过了。此课后习题答案对应的教材信息如下:书名:数据结构作者:顾泽元 刘文强出版社:北京航空航天大学出版社加载中,请稍候...
加载中,请稍候...
商品编号:
京 东 价:
[定价:¥]
在线客服:
服务支持:
21世纪高等学校应用型规划教材(计算机系列):新编数据结构教程
加载中,请稍候...
商品介绍加载中...
扫一扫,精彩好书免费看
京东商城向您保证所售商品均为正品行货,京东自营商品开具机打发票或电子发票。
凭质保证书及京东商城发票,可享受全国联保服务(奢侈品、钟表除外;奢侈品、钟表由京东联系保修,享受法定三包售后服务),与您亲临商场选购的商品享受相同的质量保证。京东商城还为您提供具有竞争力的商品价格和,请您放心购买!
注:因厂家会在没有任何提前通知的情况下更改产品包装、产地或者一些附件,本司不能确保客户收到的货物与商城图片、产地、附件说明完全一致。只能确保为原厂正货!并且保证与当时市场上同样主流新品一致。若本商城没有及时更新,请大家谅解!
权利声明:京东上的所有商品信息、客户评价、商品咨询、网友讨论等内容,是京东重要的经营资源,未经许可,禁止非法转载使用。
注:本站商品信息均来自于合作方,其真实性、准确性和合法性由信息拥有者(合作方)负责。本站不提供任何保证,并不承担任何法律责任。
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
加载中,请稍候...
浏览了该商品的用户还浏览了
加载中,请稍候...
七日畅销榜
新书热卖榜
iframe(src='///ns.html?id=GTM-T947SH', height='0', width='0', style='display: visibility:')

我要回帖

更多关于 非结构化数据库有哪些 的文章

 

随机推荐