数据结构基础 单链表的设计与实现之高级操作

时间:2023年04月11日

/

来源:gjghfh

/

编辑:本站小编

收藏本文

下载本文

下面是小编给大家带来关于数据结构基础 单链表的设计与实现之高级操作,本文共8篇,一起来看看吧,希望对您有所帮助。本文原稿由网友“gjghfh”提供。

篇1:数据结构基础 单链表的设计与实现之高级操作

链表的链接:

将第二条链表的所有内容链接到第一条链表之后, 其完整实现代码与解析如下:

//链表的链接templatevoid MyList::concatenate(const MyList&list){ if (isEmpty)//如果自己的链表为空 { first = list.first; return ; } else if (list.isEmpty()) //如果第二条链表为空 { return ; } Node*endNode = first->next; //找到第一条链表的末尾节点 while (endNode->next != NULL) { endNode = endNode->next; } //找到第二条链表的第一个真实元素 Node*secondListNode = (list.first)->next; //注意: 需要将第二个链表中的元素值copy出来 //不能直接将第二条链表的表头链接到第一条链表的表尾 //不然在析构函数回收内存时会发生错误(即:同一段内存释放两次) while (secondListNode != NULL) { Node*newNode = new Node(secondListNode->data); newNode->next = NULL; endNode->next = newNode; //两条链表同时前进 endNode = endNode->next; secondListNode = secondListNode->next; }}

链表的反转:

基本思想:

遍历一遍链表,利用一个辅助指针(此处为指针r),存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历,

//链表的反转templatevoid MyList::invort(){ if (!isEmpty()) { //p指向正向链表的第一个真实节点 //随后, p也会沿正方向遍历到链表末尾 Node*p = first->next; //q会成为倒向的第一个真实节点 //首先将q设置为NULL: 保证反向之后 //最后一个元素的指针域指向NULL, 以表示链表结束 Node*q = NULL; while (p != NULL) {Node*r = q; //暂存q当前指向的节点//q后退(沿着正向后退)q = p;//p前进(沿着正向前进), 保证p能够始终领先q一个位置p = p ->next;//将指针逆向反转//注意:一点要保证这条语句在p指针移动之后运行,//不然p就走不了了...(因为q改变了指针的朝向)q ->next = r; } //此时q成为反向链表的第一个真实元素 //但是为了维护像以前一样的first指针指向一个无用的节点(以使前面的操作不会出错) //于是我们需要将first的指针域指向q first->next = q; }}

链表打印:

重载MyList的<<运算符 p=“p” 以供测试之用=“以供测试之用<” 输出链表所有元素=“输出链表所有元素,”>

//显示链表中的所有数据(测试用)templateostream &operator<<(ostream &os, const MyList&list){ for (Node*searchNode = list.first ->next;searchNode != NULL;searchNode = searchNode ->next) { os << searchNode ->data; if (searchNode ->next != NULL) //尚未达到链表的结尾cout << “ ->”; } return os;}

附-测试代码:

int main(){ cout << “------------ 1 ------------” << endl; MyListfirst; for (int i = 0; i < 5; ++i) { first.insert(i+1, i+1); } first.remove(5); MyListsecond; for (int i = 0; i < 5; ++i) { second.insert(i+6, i+1); } second.insertFront(5); second.insert(88, 7); cout << “Before concatenate...” << endl; cout << “first: ” << first << endl; cout << “second: ” << second << endl; cout << “After concatenate...” << endl; first.concatenate(second); cout << “first: ” << first << endl; cout << “second: ” << second << endl; cout << “\\n------------ 2 ------------” << endl; MyListchList; for (char ch = '0'; ch <= '9'; ++ ch) { chList.insertFront(ch); } cout << “Before invort...” << endl; cout << chList << endl; cout << “After invort...” << endl; chList.invort(); cout << chList << endl; cout << “After remove('5')...” << endl; chList.remove('5'); cout << chList << endl; cout << “\\n------------ 3 ------------” << endl; MyListdList; dList.insert(1.1, 1); dList.insertFront(2.2); cout << dList << endl; return 0;}

篇2:C实现通用数据结构单链表

单链表的接口定义:

1、list_init

void list_init(List *list, void (*destroy)(void *data));

返回值 void

描述  初始化由参数list指定的链表,该函数必须在链表做其他操作之前调用,当调用list_destroy时,destroy参数提供了一种释放动态分配数据的方法,如果链表采用malloc动态分配的数据,destroy应该设置为free来释放这些数据

复杂度 O(1)

2、list_destroy

void list_destroy(List *list);

返回值 void

描述  销毁由参数list指定的链表,调用该函数以后任何函数都不能再执行,除非重新执行list_init函数。list_destroy将list中的所有元素都移除,每移除一个元素都会调用此函数

复杂度 O(n) n为链表元素的个数

3、list_ins_next

int list_ins_next(List *list, ListElmt *element, const void *data);

返回值 如果插入元素成功返回0,否则返回-1

描述  在指定的list的element元素后面插入一个元素,如果element为NULL,则在链表的头部插入新的元素,该元素包含一个指向data的指针

复杂度 O(1)

4、list_rem_next

int list_rem_next(List *list, ListElmt *element, void **data);

返回值  如果移除元素成功返回0,否则返回-1

描述  移除在指定的list的element后面的那个元素,如果element为NULL,则移除链表的头元素,调用返回后,data指向已经移除元素的数据

复杂度 O(1)

5、list_size

int list_size(const List *list);

返回值  如果list中元素的个数

描述  这是一个宏,用来计算指定list中元素的个数

复杂度 O(1)

6、list_head

ListElmt *list_head(const List *list);

返回值  指向链表头元素的指针

描述  这是一个宏,返回由参数list指定的链表头元素的指针

复杂度 O(1)

7、list_tail

ListElmt *list_tail(const List *list) ((list)->tail);

返回值  指向链表尾元素的指针

描述  这是一个宏,返回由参数list指定的链表尾元素的指针

复杂度 O(1)

8、list_is_head

int list_is_head(const ListElmt *element);

返回值  如果element元素是链表头元素返回0,否则返回-1

描述  这是一个宏,用来判断element元素是否是list的头元素

复杂度 O(1)

9、list_is_tail

int list_is_tail(const ListElmt *element);

返回值  如果element元素是链表尾元素返回0,否则返回-1

描述  这是一个宏,用来判断element元素是否是list的尾元素

复杂度 O(1)

10、list_data

void *list_data(const ListElmt *element);

返回值  结点中保存的数据

描述  这是一个宏,返回由element元素中保存的数据

复杂度 O(1)

11、list_next

ListElmt *list_next(const ListElmt *element) ;

返回值  返回element所指定结点的下一个结点

描述  这是一个宏,返回链表中element所指定结点的下一个结点

复杂度 O(1)

单链表的实现和分析

抽象数据类型的头文件(list.h):

#ifndef LIST_H

#define LIST_H

#include

//为单链表的结点定义一个结构体.

typedef struct ListElmt_ {

void       *data; //数据域

struct ListElmt_ *next;  //指针域

} ListElmt;

//为单链表定义一个结构体.

typedef struct List_ {

int        size;  //容量

int        (*match)(const void *key1, const void *key2);  //匹配函数

void       (*destroy)(void *data);  //撤销操作

ListElmt     *head; //头指针

ListElmt     *tail; //尾指针

} List;

//公共接口

void list_init(List *list, void (*destroy)(void *data));

void list_destroy(List *list);

int list_ins_next(List *list, ListElmt *element, const void *data);

int list_rem_next(List *list, ListElmt *element, void **data);

#define list_size(list) ((list)->size)

#define list_head(list) ((list)->head)

#define list_tail(list) ((list)->tail)

#define list_is_head(list, element) ((element) == (list)->head ? 1 : 0)

#define list_is_tail(element) ((element)->next == NULL ? 1 : 0)

#define list_data(element) ((element)->data)

#define list_next(element) ((element)->next)

#endif

初始化单链表:

void list_init(List *list, void (*destroy)(void *data)) { //初始化list

list->size = 0;

list->destroy = destroy; //设置为定义的析构函数

list->head = NULL;

list->tail = NULL;

return;

}

回收单链表:

void list_destroy(List *list) {

//移除每一个元素

while (list_size(list) >0) {

if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destroy != NULL) { //不断地移除链表的头结点

list->destroy(data); //调用一个用户定义的函数来释放动态分配的数据.

}

}

//现在没有操作了,释放结构体作为预防措施

memset(list, 0, sizeof(List));

return;

}

插入新节点作为指定结点的直接后继结点:

int list_ins_next(List *list, ListElmt *element, const void *data) {

ListElmt *new_element;  //为结点动态分配存储空间

if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) //假如分配失败

return -1;

// 将元素插入链表

new_element->data = (void *)data;

if (element == NULL) {

//插入到链表的头部

if (list_size(list) == 0)

list->tail = new_element;

new_element->next = list->head;

list->head = new_element;

} else {

//插入到除了链表头部以外指定的其他地方

if (element->next == NULL)

list->tail = new_element;

new_element->next = element->next;

element->next = new_element;

}

list->size++; //表长增加

return 0;

}

删除指定结点的直接后继结点:

int list_rem_next(List *list, ListElmt *element, void **data) {

ListElmt *old_element;

//不允许从一个空的list中移除元素.

if (list_size(list) == 0)

return -1;

// 从list中移除元素.

if (element == NULL) {

// 移除表头的结点.

*data = list->head->data;

old_element = list->head;

list->head = list->head->next;

if (list_size(list) == 1) //如果list只有一个元素,则直接删除尾结点

list->tail = NULL;

} else {

// 移除非头结点.

if (element->next == NULL)

return -1;

*data = element->next->data;

old_element = element->next;

element->next = element->next->next;

if (element->next == NULL) //移除指定结点后,后继为NULL,则用尾结点指向

list->tail = element;

}

//释放分配的抽象数据类型.

free(old_element);

//调整list的长度.     *

list->size--;

return 0;

}

注意:list_size、list_head、list_tail、list_is_head、list_is_tail、list_data、list_next 这些宏实现了链表中的一些简单操作,它们提供了快速访问和检测结构体成员的能力,

这些操作的时间复杂度都是O(1)

完整的测试代码如下:

// Completed on .10.22 21:00

// Language: C99

//

// 版权所有(C)codingwu (mail: oskernel@126.com)

// 博客地址:www.cnblogs.com/archimedes/

#include

#include

#include “list.h”

static void print_list(const List *list) {

ListElmt *element;

int *data, i;

fprintf(stdout, “List size is %d\\n”, list_size(list));

i = 0;

element = list_head(list);

while (1) {

data = list_data(element);

fprintf(stdout, “list[%03d]=%03d\\n”, i, *data);

i++;

if (list_is_tail(element))

break;

else

element = list_next(element);

}

return;

}

int main(int argc, char **argv) {

List list;

ListElmt *element;

int *data, i;

//初始化list

list_init(&list, free);

element = list_head(&list);

for (i = 10; i >0; i--) {

if ((data = (int *)malloc(sizeof(int))) == NULL)

return 1;

*data = i;

if (list_ins_next(&list, NULL, data) != 0) //逐个插入元素

return 1;

}

print_list(&list);  //打印初始list

element = list_head(&list); //指向头结点

for (i = 0; i < 7; i++)

element = list_next(element);

data = list_data(element);

fprintf(stdout, “Removing an element after the one containing %03d\\n”, *data);

if (list_rem_next(&list, element, (void **)&data) != 0) //删除指定结点

return 1;

print_list(&list);

fprintf(stdout, “Inserting 011 at the tail of the list\\n”);

*data = 11;

if (list_ins_next(&list, list_tail(&list), data) != 0) //插入指定结点

return 1;

print_list(&list);

fprintf(stdout, “Removing an element after the first element\\n”);

element = list_head(&list);

if (list_rem_next(&list, element, (void **)&data) != 0)

return 1;

print_list(&list);

fprintf(stdout, “Inserting 012 at the head of the list\\n”);

*data = 12;

if (list_ins_next(&list, NULL, data) != 0)

return 1;

print_list(&list);

fprintf(stdout, “Iterating and removing the fourth element\\n”);

element = list_head(&list);

element = list_next(element);

element = list_next(element);

if (list_rem_next(&list, element, (void **)&data) != 0)

return 1;

print_list(&list);

fprintf(stdout, “Inserting 013 after the first element\\n”);

*data = 13;

if (list_ins_next(&list, list_head(&list), data) != 0)

return 1;

print_list(&list);

i = list_is_head(&list, list_head(&list));

fprintf(stdout, “Testing list_is_head...Value=%d (1=OK)\\n”, i);

i = list_is_head(&list, list_tail(&list));

fprintf(stdout, “Testing list_is_head...Value=%d (0=OK)\\n”, i);

i = list_is_tail(list_tail(&list));

fprintf(stdout, “Testing list_is_tail...Value=%d (1=OK)\\n”, i);

i = list_is_tail(list_head(&list));

fprintf(stdout, “Testing list_is_tail...Value=%d (0=OK)\\n”, i);

fprintf(stdout, “Destroying the list\\n”);

list_destroy(&list);

return 0;

}

篇3:数据结构基础 循环队列的设计与实现

队列

队列简称队, 也是一种操作受限的线性表, 只允许在表的一端进行插入, 而在表的另一端进行删除.其特点为”先进先出(FIFO)”,故又称为先进先出的线性表,简单队列如图所示:

循环队列

顺序队列有一个先天不足, 那就是空间利用率不高, 会产生”假溢出”现象,即:其实队列中还有空闲的空间以存储元素, 但我们在判断队列是否还有空间时, 队列告诉我们队列已经满了, 因此这种溢出并不是真正的溢出, 在data数组中依然存在可以放置元素的空位置, 所以说这是一种”假溢出”;

于是我们就引入了循环队列的概念, 将顺序队列臆造为一个环状的空间, 即把存储队列元素的表从逻辑上看成一个环, 称为循环队列,其示意图如下:

注意:如图中所示,我们的循环队列为了在实现上的便利, 会有一个位置的空闲, m_front(如图中的front)指针总会指向一个元素值为空的位置,因此(m_front+1)%capacity才真正的指向队首元素, 而m_rear(图中为rear)才指向一个真实存在的队尾元素;<?www.2cto.com/kf/ware/vc/“ target=”_blank“ class=”keylink“>vcD48cD48cHJlIGNsYXNzPQ==”brush:java;“>//循环队列的实现与解析templateclass MyQueue{ templatefriend ostream &operator<<(std::ostream &os, const MyQueue&queue);public: MyQueue(int queueSize = 64); ~MyQueue; void push(const Type &item); void pop() throw (std::range_error); const Type &front() const throw (std::range_error); const Type &rear() const throw (std::range_error); bool isEmpty() const;private: Type *m_queue; int m_front; //队首指针(其实(m_front+1)%capacity才真正的指向队首元素) int m_rear; //队尾指针 int capacity; //队列的内存大小, 但实际可用的大小为capacity-1};

templateMyQueue::MyQueue(int queueSize): capacity(queueSize){ if (queueSize< 1) throw std::range_error(”queueSize must >= 1“); m_queue = new Type[capacity]; if (m_queue == NULL) throw std::bad_alloc(); m_front = m_rear = 0;}

templateMyQueue::~MyQueue(){ delete []m_queue; m_queue = NULL; m_front = m_rear = 0; capacity = -1;}

templateinline bool MyQueue::isEmpty() const{ return m_front == m_rear;}

templateinline void MyQueue::push(const Type &item){ if ((m_rear+1)%capacity == m_front) //队列已满 { Type *newQueue = new Type[2 * capacity]; //新队列的长度为原队列的2倍 if (newQueue == NULL)throw std::bad_alloc(); int start = (m_front+1)%capacity; //数据序列的起始地址 if (start<= 1) //队列指针尚未回绕 {//只需拷贝一次:从start所指向的元素直到m_rear所指向的元素//std::copy(m_queue+start, m_queue+start+capacity-1, newQueue);std::copy(m_queue+start, m_queue+m_rear+1, newQueue); } else {//需要拷贝两次//1:从start所指向的元素直到数组(不是队列)末尾std::copy(m_queue+start, m_queue+capacity, newQueue);//2:从数组(不是队列)起始直到队列末尾std::copy(m_queue, m_queue+m_rear+1, newQueue+capacity-start); } //重新设置指针位置:详细信息请看下面图解 m_front = 2*capacity-1; m_rear = capacity-2; capacity *= 2; delete []m_queue; m_queue = newQueue; } //队尾指针后移 //注意:此处m_front+1可能需要回绕 m_rear = (m_rear+1)%capacity; m_queue[m_rear] = item;}

templateinline const Type &MyQueue::front() constthrow (std::range_error){ if (isEmpty()) throw range_error(”queue is empty“); //注意:此处m_front+1可能需要回绕 return m_queue[(m_front+1)%capacity];}templateinline const Type &MyQueue::rear() constthrow (std::range_error){ if (isEmpty()) throw range_error(”queue is empty“); return m_queue[m_rear];}

templateinline void MyQueue::pop()throw (std::range_error){ if (isEmpty()) throw range_error(”queue is empty“); //注意:此处m_front+1可能需要回绕 m_front = (m_front+1)%capacity; m_queue[m_front].~Type(); //显示调用析构函数以销毁(析构)对象}

//输出队列所有内容以做测试templateostream &operator<<(ostream &os, const MyQueue&queue){ for (int i = (queue.m_front+1)%(queue.capacity);i<= queue.m_rear; /**空**/ ) { os<< queue.m_queue[i]<< ‘ ‘; if (i == queue.m_rear)break; elsei = (i+1)%(queue.capacity); } return os;}

补充说明

当队列已满时的两类扩充操作:

扩充之后的内存布局:

附-测试代码:

int main(){ MyQueuecQueue(3); cQueue.push(‘A‘); cQueue.push(‘B‘); //因为cQueue实际能够用的大小为2, 所以此处会对数组进行放大 cQueue.push(‘C‘); cout<< cQueue<< endl; cout<< ”front = “<< cQueue.front()<< ”, rear = “<< cQueue.rear()<< endl; cQueue.pop(); cQueue.pop(); cQueue.push(‘D‘); cQueue.push(‘E‘); cQueue.push(‘F‘); //此时queue的m_rear会进行回绕 cQueue.push(‘G‘); cQueue.pop(); cQueue.push(‘H‘); //此时队列已满, 再添加元素则会进行对队列扩张 //此时m_rear已经回绕, 则会触发两次拷贝操作 cQueue.push(‘I‘); //验证是否能够正常工作 cout<< cQueue<< endl; cout<< ”front = “<< cQueue.front()<< ”, rear = “<< cQueue.rear()<< endl; for (char ch = ‘1‘; ch<= ‘9‘; ++ch) cQueue.push(ch); for (int i = 0; i< 4; ++i) cQueue.pop(); cout<< cQueue<< endl; cout<< ”front = “<< cQueue.front()<< ”, rear = “<< cQueue.rear()<< endl; return 0;}

篇4:高职《数据结构》课程的设计与实现

高职《数据结构》精品课程的设计与实现

该文就高职<数据结构>精品课程的设计与实现作了初步的探讨,同时,简要介绍我们在尝试数据结构案例教学中的.一些体会.

作 者:王科 WANG ke  作者单位:湖北省荆州职业技术学院,信息技术系,湖北,荆州,434020 刊 名:电脑知识与技术 英文刊名:COMPUTER KNOWLEDGE AND TECHNOLOGY 年,卷(期): 5(23) 分类号:G434 关键词:数据结构   案例教学法   工作过程导向  

篇5:长沙市基础空间数据库的设计与实现

长沙市基础空间数据库的设计与实现

本文针对长沙市基础空间数据库建库中的内容、组织方式、数据库的结构与系统实现等有关问题进行了讨论,提出面向数字城市和WebGIS等应用服务的空间数据管理和解决方案,目前系统运行良好,并为长沙市规划局提供着空间信息服务.

作 者:杨品福 杜清运 李跃 何文 YANG Pin-fu DU Qing-yun LI Yue HE Wen  作者单位:杨品福,杜清运,YANG Pin-fu,DU Qing-yun(武汉大学资源与环境科学学院,武汉,430079)

李跃,何文,LI Yue,HE Wen(长沙市勘测设计研究院,长沙,410007)

刊 名:测绘科学  ISTIC PKU英文刊名:SCIENCE OF SURVEYING AND MAPPING 年,卷(期): 31(6) 分类号:P208 关键词:数字城市   空间数据库   数据模型   ArcSDE  

篇6:基于基础地理信息数据库的制图设计与实现

基于基础地理信息数据库的制图设计与实现

辽宁省测绘局于开始正式启动辽宁省基础地理信息数据库建设工程,该建设工程的目标之一是实现了图库一体化功能.本文详细介绍了基于辽宁省基础地理信息数据库的`制图设计与实现.

作 者:肖文芳 Xiao Wenfang  作者单位:辽宁省基础地理信息中心,辽宁,沈阳,110034 刊 名:现代测绘 英文刊名:MODERN SURVEYING AND MAPPING 年,卷(期): 32(1) 分类号:P208 关键词:基础地理信息数据库   制图  

篇7:基于SCL的航天器遥控操作平台设计与实现

基于SCL的航天器遥控操作平台设计与实现

为了实现对航天器的透明控制,航天器控制中心开发设计了遥控操作平台.首先提出了遥控操作平台的.硬件组成及运行环境;其次结合航天器测控任务的需求,进行了软件功能设计,将遥控操作平台分为四个层次、六大功能,并详细描述了其数据流图;最后明确了遥控操作平台的内部、外部接口以及安全性措施.该遥控操作平台已成功地完成了我国同步和近地卫星早期以及长期管理阶段的测控任务,极大地提高了我国航天器测控能力和测控网资源的运行效率.

作 者:杨永安 余培军 陈建平冯祖仁 崔卫华 YANG Yong-an YU Pei-jun CHEN Jian-ping FENG Zu-ren CUI Wei-hua  作者单位:杨永安,YANG Yong-an(西安交通大学,西安,710049;西安卫星测控中心,西安,710043)

余培军,陈建平,崔卫华,YU Pei-jun,CHEN Jian-ping,CUI Wei-hua(西安卫星测控中心,西安,710043)

冯祖仁,FENG Zu-ren(西安交通大学,西安,710049)

刊 名:宇航学报  ISTIC PKU英文刊名:JOURNAL OF ASTRONAUTICS 年,卷(期): 27(3) 分类号:V448.132 关键词:航天器   测控系统   SCL   遥控操作平台  

篇8:计算机基础课程远程教学系统的设计与实现

摘要:本文讨论了基于Web的计算基础课程远程教学系统的设计思想及其实现方法。教师使用该系统可以进行网上授课、布置作业、批改作业、出试卷、评卷等;学生使用该系统在浏览器中观看教师授课视频图象(广播或点播)、在网上做作业、提交作业、考试、答疑或课堂讨论。

1.引言

随着多媒体技术和网络通信技术的发展,基于Internet的计算机远程教学作为一种全新的教学手段,越来越受到人们的关注。计算机远程教学是指利用多媒体技术和网络通信技术,在网络环境下开展的教学活动。它有着传统教学模式所无可比拟的优点,它创造了一种全新的教学模式,打破了传统教学模式在时间、空间上的限制,采用了先进的教学手段和教学方法,大大提高了教学效率和教学效果,使教学活动上了一个新台阶。

作者所在单位承担我校除计算机系以外的所有系所的计算机基础公共课(包括《计算机应用基础》、《C语言》、《Foxpro》等课程)的教学任务,每学期平均有3000多学生,各教师均负责2~3个班共200~300多人的教学,教学任务繁重。为了使教师能通过先进的教学手段提高教学效率,增强学生应用Internet网络服务的能力,以此来加强和巩固对课程内容的理解和掌握,我们从1999年开始,开发了《计算机基础课程远程教学》系统(以下简称《远程教学系统》)。在Internet/Intranet环境下实现作业、考试、授课、答疑/辅导等功能,使用一年多来,取得了很好的教学效果,以下讨论该系统的设计与实现方法。

2.《远程教学系统》的体系结构

《远程教学系统》是在Internet/Intranet环境下实现的,是典型的浏览器/服务器模式。服务器以Windows NT 4/2000 Server为操作系统平台,Microsoft SQL Server 7.0为RDBMS,客户端通过浏览器访问系统提供的服务。系统不允许匿名访问,它要求用户提供帐号/密码,通过验证后才能进入系统主页,以此追踪用户身份。本系统将用户分为三类:系统管理员、教师、学生,他们都有各自的主页,访问系统的权限也不相同。其中权限最高的为管理员,其次为教师,最低为学生。权限高的能访问其下级所能访问的所有资源,反之则不然。例如教师能进入学生主页,而学生则不能访问教师主页所提供的功能(布置作业、批改作业等)。本系统可同时为不同课程的多组教师/学生(上一门课的教师及其学生为一组)提供服务,它们之间既有一定的隔离性(例如某个教师帐号不能批改属于另一个教师的学生的作业等),又有资源的共享性(例如公共作业、试题的共享等),很好地解决了本单位各个教师负责不同班级,课程也有所不同的问题。《远程教学系统》体系结构按用户角色的不同,划分如下:

图1 《远程教学系统》体系结构

2.1 管理员模块

由于《计算机基础课程远程教学》系统可同时为多组教师/学生提供服务,各组间的课程不尽相同,因此教师/学生组间应具有一定的隔离性。例如一门课程的教师对其学生具有管理权,但不能对属于其它教师的学生进行管理、某个学生只能访问其教师的作业等。因此系统主页需要教师或学生均以帐号/密码登录后才能访问,以此追踪用户访问系统资源的身份。而用户帐号的开设与删除、教师与学生的对应关系、课程名称、学生人数等信息,由系统管理员负责管理。这里,我们将系统资源访问帐号作为操作系统帐号开设,由Windows NT和Web服务器IIS负责进行用户验证。这样做的好处,一是可以充分利用操作系统的安全机制,使操作系统与数据库服务器(SQL Server)无缝集成;二是可同时为用户提供其它辅助服务,如:电子邮件、个人主页、FTP服务等。使系统应用与课程内容紧密结合,学生在应用系统的使用过程中可进一步加深对课程内容的理解。

2.2 教师模块

教师模块中包含了教师授课所需的各种功能。如:网上实时授课广播、布置作业、批改作业、出试卷、评卷、考试结果统计分析、网上答疑、课程资料(素材)制作、学生帐号管理(修改学生密码)、设置联机会议等。系统使用组件对象模型(COM)以及Office Automation技术自动批改《计算机应用基础》课程作业并登记成绩。教师可对作业结果进行查询、统计。教师可利用OutLook向系统请求联机会议,以此进行网上答疑、群体或个别辅导。

2.3 学生模块

学生模块包含查看教师布置的作业、(在网上或本地)做作业、测验(考试)、教师授课视频广播收看、点播、网上答疑、课程资源浏览、辅助服务等。学生使用浏览器访问系统主页时,需要提供帐号/密码进行用户验证,通过验证后,在浏览器关闭之前,均以该帐号身份访问系统资源。《计算机应用基础》课程的作业可直接在浏览器中完成并提交,对于《C语言》课程作业,为学生提供Web界面,完成作业程序的编辑、编译、链接、运行,一气呵成。远程考试功能既提供选择题形式的传统笔试试题,也提供实际操作形式的试题。考试通过WWW界面进行,有时间限制。学生在规定时限之前完成考试内容时可通过”交卷\"按钮提交试卷;若考试时限到达时学生仍未交卷,则系统自动将考生当前的考试结果提交。试卷的批改、考试结果的统计均由程序自动完成。自我测验功能则提供测验试卷,不限时间,由学生自主选择进行,测验完毕后系统立即评卷并给出成绩及学生测验时的选项与正确答案的对照表,以便学生查阅。为了更好地提高学生对网络的应用能力,增强学生对教学内容的兴趣,本系统为每位使用《计算机公共课远程教学》系统的学生和教师提供Email、FTP、个人主页、BBS、联机会议(在线聊天Chat、应用程序共享、白板)、等功能。让学生在实际操作中提高对课程内容的理解以及对课程学习的兴趣。另外,本系统还配备资源库,内置与教学内容相关或与网络应用相关的多媒体资料,供学生课外浏览、学习。

判断单链表中是否有环,计算出环的首地址 C语言实现

下载数据结构基础 单链表的设计与实现之高级操作(整理8篇)
数据结构基础 单链表的设计与实现之高级操作.doc
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档
最新范文更多
    热门文章
      猜你喜欢
      点击下载本文文档