链表的数组实现 令链表的所有元素在数组中保持紧凑 《算法导论》10.3-4

  • 让长度为m的链表的所有元素占用数组的前m个位置。
  • 假设数组总长度为SIZE,用一个变量freeHead记录空闲表的起始下标, 则[freeHead, SIZE)的范围内的对象全部属于自由表。用一个Object对象list表示链表头。
  • 当从链表的任意位置删除元素时,比如下标为pos的元素,那么就让下标为pos和freeHead-1的元素互换在链表中的位置,然后删除互换后下标为freeHead-1的元素,也就相当于删除了互换前下标为pos的元素,这样一来,就可以保证所删除元素的位置始终是自由表头freeHead的前一个位置,于是保持了自由表中元素下标的连续性。freeHead将数组元素分为前半部分的链表元素和后半部分的自由元素。
#include <cassert>
#include <iostream>
using namespace std;

struct Object
{
    int prev;
    int key;
    int next;
};
constexpr int SIZE = 10;
Object array[SIZE];
int freeHead = 0;
Object list;
void Init()
{
    list.prev = -1;
    list.next = -1;
}

int AllocateObject()
{
    if(freeHead == SIZE)
        return -1;
    array[freeHead].prev = array[list.next].prev;
    array[freeHead].next = array[list.prev].next;
    array[list.next].prev = freeHead;
    array[list.prev].next = freeHead;
    return freeHead++;
}

void FreeObject(int pos)
{
    assert(pos >= 0 && pos < freeHead);
    int listTail = --freeHead;
    //delete array[pos] from list
    array[array[pos].prev].next = array[pos].next;
    array[array[pos].next].prev = array[pos].prev;
    //move array[listTail] to array[pos]
    array[pos] = array[listTail];
    int listTailPrev = array[listTail].prev;
    int listTailNext = array[listTail].next;
    array[listTailPrev].next = pos;
    array[listTailNext].prev = pos;
}

void Test()
{
    Init();
    for(int i = 0; i != SIZE; ++i)
        cout << AllocateObject() << "\t";
    cout << endl;                   //占用0~9全部元素
    cout << AllocateObject() << endl;// -1
    for(int i = 0; i != SIZE/2; ++i)
        FreeObject(i);              //释放下标为0 1 2 3 4的5个元素
    for(int i = 0; i != SIZE/2; ++i)
        cout << AllocateObject() << "\t";
    cout << endl;                //由于链表中元素保持紧凑,所以实际空闲下来的元素下标为5 6 7 8 9
}
//运行结果为
0 1 2 3 4 5 6 7 8 9
-1
5 6 7 8 9

原文地址:https://www.cnblogs.com/meixiaogua/p/9782541.html

时间: 2024-11-06 00:58:07

链表的数组实现 令链表的所有元素在数组中保持紧凑 《算法导论》10.3-4的相关文章

数组 :定义一个有20个元素的数组,每一个元素的取值范围是[30 ,70],求他们的和

   //定义一个有20个元素的数组,每一个元素的取值范围是[30 ,70],求他们的和     int a[20] = {0};     int sum = 0;     for (int i = 0; i < 20; i++) {         a[i] = arc4random()%(70 - 30 + 1) + 30;         printf("%d ",a[i]);         sum += a[i];     }       printf("\n

算法导论10:栈链表的简化、队列的数组实现 2016.1.10

新年的前十天做了比较有意义的事情就是坚持每天写博客,明天就开始期末考试了,所以等假期再继续学习. 把昨天提到的S.bottom简化之后又改了栈的链表.代码如下(已折叠): #include<stdio.h> #include<stdlib.h> typedef struct _node{ int num; struct _node *next; }node; node *s; void build(node *&S) { s=(node *)malloc(sizeof(no

算法导论10.2链表

带哨兵的双向链表,代码中我使用了nullptr,所以需要编译器升级,我的编译器是gcc/g++ 4.7.0这是可以的,编译的时候加参数-std=c++0x 节点中还可能有卫星元素 /* * IA_10.2LinkedLists.cpp * * Created on: Feb 12, 2015 * Author: sunyj */ #include <stdint.h> #include <iostream> class ListNode { public: ListNode() :

算法导论 10.1-2 用一个数组实现两个栈

一.题目 用一个数组A[ 1....N ]实现两个栈,除非数组的每一个单元都被使用,否则栈例程不能有溢出,注意PUSH和POP操作的时间应为O(1). 二.解法 对于一个数组,由它的两端作为栈底,栈向数组中间扩展.当数组中每个元素被用到时,栈满. 三.代码 struct Node; typedef Node *ComStack; struct Node { int Capacity; int TopL; int TopR; ElementType *Array; }; ComStack Crea

算法导论之链表

一.概念 (1)数组的线性序是由数组的下标决定的,链表中的顺序是由各对象中的指针所决定的 (2)链表结点结构 node *prev; node *next; int key; (3)链表结点 node *head; node *nil;//哨兵 (4)对链表的操作 LIST-SEARCH(L, k) LIST-INSERT(L, x) LIST-DELETE(L, x) (5)哨兵是个哑对象,可以简化边界条件 二.代码 (1)没有哨兵的情况 [cpp] view plain copy print

《数据结构》之数组结构和链表

1:间接寻址的基本概念{ 间接寻址就是二级指针的利用,指向指针的指针,一维数组,二维数组.间接寻址在此特指其一维数组的含义: 间接寻址是一维和二维数组的组合.既保留了数组的许多优点,也获得了链表的众多特色.首先,可以根据索引在O(1) 的时间内询问每个元素:其次可以采用二分在对数时间内对一个有序表进行搜索:最后,在诸如插入和删除的操作期间 不必对元素进行实际的行动} 2:间接寻址使用指针数组来跟踪每一个元素,对元素本身如何分配不设限制(可离散可连续).将实体节点转化为指针节点. 3 使用:内存池

vc++基础班[28]---动态数组及动态链表的讲解

C++中也有相应的动态数组.动态链表.映射表的模板类,就是STL中的:vector.list.map 他们属于C++标准中的一部分,对于程序的移植性来说也是不错的,但是在MFC编程中使用 CArray.CList.CMap 会更方便一些! CArray.CList.CMap 的由来?…… ①.数组的基本说明: 数组是固定大小的,相同数据类型的元素的顺序集合,每个元素在数组中有一个固定的位置. 将10个数放入数组中,假设数组的名称为number,可以称数组中第一个元素为 number[0],第二个

二叉树(一)——二叉树的基本实现(数组实现和链表实现)

1.树是一种数据结构,树的一些相关的术语: 结点的度:一个结点的后继结点的个数. 树的度:树中度值最大的结点的度被称为树的度. 树的深度:树的层次数. 分支结点:度值大于0的结点,分支结点至少含有一个后继,分支结点也称为非终端结点. 叶子结点:树中的度值为0的结点. 双亲结点:树中某个结点的前驱结点,也成为父节点. 子女结点:树中某结点的后继结点. 兄弟结点:树中同一层的结点. 2.二叉树 (1)二叉树是一种特殊的树,树的度值最大为2. (2)二叉树的表示: A /      \ B     

数组队列 与 链表队列

做了些实验,感觉 用链表实现队列 比 用数组实现队列 性能好 进出队的每秒操作数比较 数组队列 enqueue 37,037 dequeue 4,166,666 链表队列 enqueue 277,778 dequeue 666,667 先入队n次,再出队n次的运行时间比较,单位是秒 出入队次数 | 数组队列运行时间 | 链表队列运行时间 1,000 0.01 0.01 10,000 0.04 0.04 100,000 2.7 0.4 1,000,000 4 最后一组,数组队列的半天没运行出来 下