这个作业是对上一次作业3的一个补充。单链表的实现在上一个作业3已经给出。
1.循环单链表
循环单链表和单链表差不多,只是将终端结点的指针域由空指针变为指向头结点,而且为了查找开始结点和尾结点的时间复杂度都为O(1),所有在循环列表中一般都由指向终端结点的尾指针来标识循环列表。
増删改查的实现和单链表一样。
2.双向链表
双向链表的结点在单链表的基础上增加了一个指向上一个结点的指针域。
template <class T>
struct DulNode
{
T data;
DulNode <T> *prior,* next;
}
双向链表和单链表在求表长,按位置查找,按值查找遍历等操作上的实现都差不多,不同的只是插入和删除操作。
template <class A>
void ListList< A> ::Insert(int i ,A x)
{
p=first;
count =0;
while (p!=NULL&&count<i-1)
{
p=p->next;
count++;
}
if(p==NULL)
throw "位置";
else
{
s=new Node;
s->prior=p;
s->next=p->next;
p->next->prior=s;
p->next=s;
}
}
template<class A>
A LinkList<A>::Delete(int i)
{
p=first;
count=0;
while (p!=NULL&&count<i-1)
{
p=p->next;
count++;
}
if(p==NULL||p->next==NULL)
throw"位置";
else
{
(p->prior)->next=p->next;
(p->next)->prior=p->prior;
delete q;
return x;
}
3.双向循环链表
双向循环链表和双向链表差不多,就是将头指针的prior指针域指向终端结点,将终端结点的next指针域指向头结点。
4.内存对齐
内存对齐”应该是编译器的“管辖范围”。编译器为程序中的每个“数据单元”安排在适当的位置上。但是C语言的一个特点就是太灵活,太强大,它允许你干预“内存对齐”。
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
5.hash散列
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。