C语言实现静态链表的方法

在动手之前我一直以为静态链表和动态链表没有什么差别,细细一想才发现,原来静态链表之中隐藏着一个非常值得讨论的话题——内存管理。

静态链表的“静态”二字是指内存的来源为静态内存(通常用全局数组)。与动态链表不同,在静态链表中节点内存的申请与释放都需要自行维护,由于这里是链表,也很容易想到将空余的节点链接起来形成一个free_list,每次需要时从free_list头部取出一个节点,释放时再将节点加到头部,这样就能够非常容易的实现链表的其他操作。

代码如下:

// 静态链表 的实现
 #include <stdio.h>

#define MAXN 16 // capacity of list.
 typedef int element; // element type.

// define boolean type:
 typedef int bool;
 #define true -1
 #define false 0

#define NPTR -1 // null pointer definition. can not between 0 to MAXN-1.
 typedef int pointer;

#define DEBUGVAL(x) printf("%s: %d\n", #x, (x)); // a macro for debug.

struct __node
 {
     element data;
     pointer next;
 }SLList[MAXN];
 pointer ifree, idata;

#define nextof(p) SLList[p].next
 #define dataof(p) SLList[p].data

#define _alloc(d) ifree; dataof(ifree)=(d); ifree != NPTR ? ifree=nextof(ifree) : NPTR
 #define _free(p)  nextof(p)=ifree; ifree = p

void init()
 {
     int i;
     ifree = 0;
     idata = NPTR;
     for( i=0; i < MAXN-1; i++)
         nextof(i) = i+1;
     nextof(i) = NPTR;
 }

// clear all nodes.
 void clear() { init(); }

// push val to front.
 bool push_front(element val)
 {
     pointer tmp, np;
     if( ifree != NPTR ) {
         np = _alloc(val);
         nextof(np) = idata;
         idata = np;
         return true;
     }
     return false;
 }

// push val to end of list.
 bool push_back(element val)
 {
     if( idata == NPTR ) { // 空表,直接写入
         idata = _alloc(val);
         nextof(idata) = NPTR;
         return true;
     }
     if( ifree != NPTR ) { // 非空,先找到最后一个节点
         pointer last = idata, np;
         while( nextof(last) != NPTR ) last = nextof(last);       
         np = _alloc(val);
         nextof(np) = NPTR;
         nextof(last) = np;
         return true;
     }
     return false;
 }

// insert val to after p pointed node.
 bool insert_after(pointer p, element val)
 {
     if( ifree != NPTR && p != NPTR ) {
         pointer pn = _alloc(val);
         nextof(pn) = nextof(p);
         nextof(p)  = pn;       
         return true;
     }
     return false;
 }

// insert to the position in front of p.
 bool insert(pointer ptr, element val)
 {
     if( ifree == NPTR ) return false;  // 没有结点,直接返回
     if( ptr == idata ) { // 有一个节点
         pointer np = _alloc(val);
         nextof(np) = idata;
         idata = np;   
         return true;
     }
     else { // 其他情况,先找 ptr 的前驱,再插入
         pointer p = idata;
         while(  p != NPTR ) {
             if( nextof(p) == ptr ) { // find p -- the prev node of ptr.
                 return insert_after(p, val); // insert val after p.           
             }
            p = nextof(p);
         }
     }
     return false;
 }

// find element, return the prev node pointer.
 pointer find_prev(element val)
 {
     pointer p = idata;
     while(  p != NPTR ) {
         if( dataof( nextof(p) ) == val )
             return p;
         p = nextof(p);
     }
     return NPTR;
 }

// find element, return the node  pointer.
 pointer find(element val)
 {
     pointer p = idata;
     while(  p != NPTR ) {
         if( dataof(p) == val ) return p;
         p = nextof(p);
     }
     return NPTR;
 }

// pop front element.
 void pop_front()
 {
     if( idata != NPTR ) { // 将 data list 最前面的节点 移到 free list 上
 #if 0
         pointer p = idata;       
         idata = nextof(idata); // idata = nextof(idata);
         nextof(p) = ifree;  // SLList[p].next = ifree;
         ifree = p;
 #else
         pointer p = idata;
         idata = nextof(idata);
         _free(p);
 #endif
     }
 }

// pop back element.
 void pop_back()
 {
     if( idata == NPTR ) return;
     if( nextof(idata) == NPTR ) { // only 1 node.
         nextof(idata) = ifree;
         ifree = idata;
         idata = NPTR;
     }
     else { // 找到最后一个节点 p,以及它的前驱 q.
         // TODO: find the last node p, and it's perv node q.
         pointer p = idata, q;
         while( nextof(p) != NPTR ) {
             q = p;
             p = nextof( p );
         }
         // remove *p to free list, update nextof(q) to NPTR.
         nextof(p) = ifree;
         ifree = p;
         nextof(q) = NPTR;
     }
 }

void show()
 {
     pointer p = idata;
     for( ; p != NPTR; p = nextof(p) ) {
         printf(" %3d ", dataof(p) );
     }
     printf("\n");
 }

#define INFOSHOW
 void info()
 {
 #ifdef INFOSHOW
     int i;   
     DEBUGVAL(ifree);
     DEBUGVAL(idata);
     puts("====================\n"
         "index\tdata\tnext\n"
         "--------------------");
     for(i=0; i<MAXN; i++) {
         printf("%d\t%d\t%d\n", i, SLList[i].data, SLList[i].next);
     }
     puts("====================\n");
 #endif
 }

/*
     测试程序:
 */
 int main()
 {
     int i;
     init();

#if 1  // push_front test:
     puts("push_front test:");
     for(i=0; i<MAXN+2; i++)    {
         push_front(2*i+1);
         show();   
     }

puts("pop_front test:");
     for(i=0; i<MAXN+2; i++)    {
         pop_front();
         show();
     }
 #endif

#if 1 // push_back test:
     puts("push_back test:");
     for(i=0; i<MAXN+2; i++)    {
         push_back((i+1)*10);
         show();   
     }

puts("pop_back test:");
     for(i=0; i<MAXN+1; i++)
     {
         pop_back();
         show();
     }
 #endif

#if 1 // insert test:
     puts("insert test:");
     for(i=0; i<MAXN+2; i++)
     {
         insert(idata, (i+1)*10);
         show();
     }
     puts("clear...\n");
     clear();
 #endif

#if 1 // insert_after test:
     puts("insert_after test:");
     push_back(-99);
     for(i=0; i<MAXN+1; i++) {
         insert_after(idata, i+1);
         show();
     }
     puts("clear...\n");
     clear();
 #endif

#if 1 // find test:
     puts("find test:");
     for(i=0; i<MAXN/2; i++) {
         push_front(MAXN-i);
         push_back(MAXN/2-i);
         //show();
     }
     show();
     info();
     for(i=0; i<MAXN; i++) {
         int val = rand()%(2*MAXN);
         pointer p = find(val);
         if( p != NPTR )
             printf("%3d %3d found at %d\n", val, dataof(p), p);
         else
             printf("%3d not found\n", val);
     }
 #endif

#if 1
     puts("\nfind_prev test:");
     for(i=0; i<MAXN; i++) {
         int val = rand()%(2*MAXN);
         pointer p = find_prev(val);
         if( p != NPTR )
             printf("%3d %3d found at %d's next.\n", val, dataof(nextof(p)), p);
         else
             printf("%3d not found\n", val);
     }
 #endif

#if 1 // find_prev and insert_after test:
     clear();
     puts("\nfind_prev and insert_after test:");
     for(i=0; i<MAXN/2; i++)    {
         push_front(MAXN/2-i);
     }
     show();
     for(i=0; i<MAXN/2; i++) {
         int val = rand()%(2*MAXN), n=-(i+1);
         pointer p = find_prev(val);
         if( p != NPTR ) {
             printf("insert %d to front of %d:", n, val);
             insert_after(p, n);
             show();
         }
     }   
 #endif

#if 1 // find and insert test:
     clear();
     puts("\nfind and insert test:");
     for(i=0; i<MAXN/2; i++)    {
         push_front(MAXN/2-i);
     }
     show();
         for(i=0; i<MAXN/2; i++) {
         int val = rand()%MAXN, n=-(i+1);
         pointer p = find(val);
         if( p != NPTR ) {
             printf("insert %d to after of %d:", n, val);
             insert_after(p, n);
             show();
         }
     }
 #endif

puts("end of main().");   
     return 0;
 }

//

测试结果如下:

代码如下:

push_front test:
    1
    3    1
    5    3    1
    7    5    3    1
    9    7    5    3    1
   11    9    7    5    3    1
   13   11    9    7    5    3    1
   15   13   11    9    7    5    3    1
   17   15   13   11    9    7    5    3    1
   19   17   15   13   11    9    7    5    3    1
   21   19   17   15   13   11    9    7    5    3    1
   23   21   19   17   15   13   11    9    7    5    3    1
   25   23   21   19   17   15   13   11    9    7    5    3    1
   27   25   23   21   19   17   15   13   11    9    7    5    3    1
   29   27   25   23   21   19   17   15   13   11    9    7    5    3    1
   29   27   25   23   21   19   17   15   13   11    9    7    5    3    1
   29   27   25   23   21   19   17   15   13   11    9    7    5    3    1
pop_front test:
   27   25   23   21   19   17   15   13   11    9    7    5    3    1
   25   23   21   19   17   15   13   11    9    7    5    3    1
   23   21   19   17   15   13   11    9    7    5    3    1
   21   19   17   15   13   11    9    7    5    3    1
   19   17   15   13   11    9    7    5    3    1
   17   15   13   11    9    7    5    3    1
   15   13   11    9    7    5    3    1
   13   11    9    7    5    3    1
   11    9    7    5    3    1
    9    7    5    3    1
    7    5    3    1
    5    3    1
    3    1
    1

push_back test:

20
   20   30
   20   30   40
   20   30   40   50
   20   30   40   50   60
   20   30   40   50   60   70
   20   30   40   50   60   70   80
   20   30   40   50   60   70   80   90
   20   30   40   50   60   70   80   90  100
   20   30   40   50   60   70   80   90  100  110
   20   30   40   50   60   70   80   90  100  110  120
   20   30   40   50   60   70   80   90  100  110  120  130
   20   30   40   50   60   70   80   90  100  110  120  130  140
   20   30   40   50   60   70   80   90  100  110  120  130  140  150
   20   30   40   50   60   70   80   90  100  110  120  130  140  150  160
   20   30   40   50   60   70   80   90  100  110  120  130  140  150  160
   20   30   40   50   60   70   80   90  100  110  120  130  140  150  160
pop_back test:
   20   30   40   50   60   70   80   90  100  110  120  130  140  150
   20   30   40   50   60   70   80   90  100  110  120  130  140
   20   30   40   50   60   70   80   90  100  110  120  130
   20   30   40   50   60   70   80   90  100  110  120
   20   30   40   50   60   70   80   90  100  110
   20   30   40   50   60   70   80   90  100
   20   30   40   50   60   70   80   90
   20   30   40   50   60   70   80
   20   30   40   50   60   70
   20   30   40   50   60
   20   30   40   50
   20   30   40
   20   30
   20

insert test:

10
   20   10
   30   20   10
   40   30   20   10
   50   40   30   20   10
   60   50   40   30   20   10
   70   60   50   40   30   20   10
   80   70   60   50   40   30   20   10
   90   80   70   60   50   40   30   20   10
  100   90   80   70   60   50   40   30   20   10
  110  100   90   80   70   60   50   40   30   20   10
  120  110  100   90   80   70   60   50   40   30   20   10
  130  120  110  100   90   80   70   60   50   40   30   20   10
  140  130  120  110  100   90   80   70   60   50   40   30   20   10
  150  140  130  120  110  100   90   80   70   60   50   40   30   20   10
  150  140  130  120  110  100   90   80   70   60   50   40   30   20   10
  150  140  130  120  110  100   90   80   70   60   50   40   30   20   10
clear...

insert_after test:
 -99    1
 -99    2    1
 -99    3    2    1
 -99    4    3    2    1
 -99    5    4    3    2    1
 -99    6    5    4    3    2    1
 -99    7    6    5    4    3    2    1
 -99    8    7    6    5    4    3    2    1
 -99    9    8    7    6    5    4    3    2    1
 -99   10    9    8    7    6    5    4    3    2    1
 -99   11   10    9    8    7    6    5    4    3    2    1
 -99   12   11   10    9    8    7    6    5    4    3    2    1
 -99   13   12   11   10    9    8    7    6    5    4    3    2    1
 -99   14   13   12   11   10    9    8    7    6    5    4    3    2    1
 -99   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1
 -99   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1
 -99   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1
clear...

find test:
   10   11   12   13   14   15   16    8    7    6    5    4    3    2    1
ifree: -1
idata: 14
====================
index    data    next
--------------------
    16    1
    8    3
    15    0
    7    5
    14    2
    6    7
    13    4
    5    9
    12    6
    4    11
    11    8
    3    13
    10    10
    2    15
    9    12
    1    -1
====================
   9 found at 14
   3 found at 11
 not found
   4 found at 9
   1 found at 15
  12 found at 8
 not found
  14 found at 4
 not found
  16 found at 0
   9 found at 14
 not found
 not found
 not found
   9 found at 14
  11 found at 10

find_prev test:
 not found
   6 found at 3's next.
 not found
 not found
   7 found at 1's next.
  12 found at 10's next.
 not found
 not found
   4 found at 7's next.
 not found
  13 found at 8's next.
 not found
   6 found at 3's next.
 not found
   7 found at 1's next.
 not found

find_prev and insert_after test:
    2    3    4    5    6    7    8
insert -4 to front of 8:   1    2    3    4    5    6    7   -4    8
insert -5 to front of 3:   1    2   -5    3    4    5    6    7   -4    8
insert -8 to front of 6:   1    2   -5    3    4    5   -8    6    7   -4    8

find and insert test:
    2    3    4    5    6    7    8
insert -2 to after of 3:   1    2    3   -2    4    5    6    7    8
insert -6 to after of 8:   1    2    3   -2    4    5    6    7    8   -6
insert -7 to after of 5:   1    2    3   -2    4    5   -7    6    7    8   -6
end of main().

(0)

相关推荐

  • C语言静态链表和动态链表

    1. 静态链表 结构体中的成员可以是各种类型的指针变量,当一个结构体中有一个或多个成员的基类型是本结构体类型时,则称这种结构体为"引用自身的结构体".如: struct link { char ch; struct link *p; } a; p是一个可以指向 struct link 类型变量的指针成员.因此,a.p = &a 是合法的表达式,由此构成的存储结构如图1所示. 图1 引用自身的结构体 例1 一个简单的链表 #include <stdio.h> stru

  • c语言链表基本操作(带有创建链表 删除 打印 插入)

    复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <malloc.h>#define LEN sizeof(struct Student)struct Student{    long num;    float score;    struct Student*next;};int n;int main(){    /*-----------------------------程序描述----------

  • C语言单循环链表的表示与实现实例详解

    1.概述: 对于一个循环链表来说,其首节点和末节点被连接在一起.这种方式在单向和双向链表中皆可实现.要转换一个循环链表,可以选择开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点.再来看另一种方法,循环链表可以被视为"无头无尾".这种列表很利于节约数据存储缓存, 假定你在一个列表中有一个对象并且希望所有其他对象迭代在一个非特殊的排列下. 指向整个列表的指针可以被称作访问指针. 用单向链表构建的循环链表 循环链表中第一个节点之前就是最后一个节点,反之亦然.循环链表的无边界使得在这

  • C语言实现双向链表

    这个小代码是我凭自己对指针和链表的理解和认识,自己实现的,没有参考其他人的代码,如果有相同的地方,那真的只是巧合,代码我在ubuntu 15.04下测试通过,可能存在很多错误和漏洞. doublelist.c /************************************************************************* > File Name: doublelist.c > Author: ChenYiLiang > Mail: chenyilian

  • 用C语言实现单链表的各种操作(一)

    最近,从新复习了一下数据结构中比较重要的几个部分,现在把自己的成果记录下来,主要就是仿照严蔚敏的<数据结构>(C 语言版),中的例子和后面的习题进行改编的.首先,是单链表的各种实现,其中,包含了一些常考的知识点.例如,单链表的逆置,单链表的合并,找到单链表的中间节点等的算法实现.下面这个是单链表的结构体的定义: 复制代码 代码如下: typedef struct LNode{ ElemType data; struct LNode *next;}LinkList; 下面的基本的单链表的操作:其

  • C语言实现带头结点的链表的创建、查找、插入、删除操作

    本文实例讲述了C语言实现带头结点的链表的创建.查找.插入.删除操作.是数据结构中链表部分的基础操作.分享给大家供大家参考.具体方法如下: #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node* next;// 这个地方注意结构体变量的定义规则 } Node, *PNode; Node* createLinklist(int length) { int i = 0; PNo

  • C语言实现静态链表的方法

    在动手之前我一直以为静态链表和动态链表没有什么差别,细细一想才发现,原来静态链表之中隐藏着一个非常值得讨论的话题--内存管理. 静态链表的"静态"二字是指内存的来源为静态内存(通常用全局数组).与动态链表不同,在静态链表中节点内存的申请与释放都需要自行维护,由于这里是链表,也很容易想到将空余的节点链接起来形成一个free_list,每次需要时从free_list头部取出一个节点,释放时再将节点加到头部,这样就能够非常容易的实现链表的其他操作. 复制代码 代码如下: // 静态链表 的实

  • C语言实现单链表实现方法

    C语言实现单链表实现方法 链表和我们之前实现过的顺序表一样,都是简单的数据结构,链表分为单向链表.双向链表.循环链表.而单向链表又分为两种实现方法,一种为带头节点的单链表,一种为不带头节点的单链表.我们来具体看看不带头节点的单链表的实现 单链表:它是一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个节点. 今天我们来实现一些单链表的简单接口 先看看单链表的结构: (为了通用性,我们将类型重命名为DataType) typedef int DataType; //

  • C语言实现静态链表

    本文实例为大家分享了C语言实现静态链表的具体代码,供大家参考,具体内容如下 注意事项: 1.这里用k申请空间,i遍历空间. 2.静态链表是利用游标来模拟指针,把固定分配的内存分成备用链表和链表两大块,在利用自制的malloc和free函数申请释放备用空间时,实现离散存储. 3.基本操作和动态链表实际上差不多,不过一个是利用p = p->next一个是使用i = L[i].cur来实现指针的后移. 4.初始化链表时,链表只有最后一个空间的cur是0, 意味是头指针,并没有任何分配的空间.备用链表的

  • 用Java实现一个静态链表的方法步骤

    什么是静态链表? 对于线性链表,也可用一维数组来进行描述.这种描述方法便于在没有指针类型的高级程序设计语言中使用链表结构. 用数组描述的链表,即称为静态链表. 在C语言中,静态链表的表现形式即为结构体数组,结构体变量包括数据域data和游标CUR. 静态链表的节点 数据域:用于存储数据元素的值 游标:即数组下标,表示直接后继元素所在数组中的位置 public class StaticLinkedListNode<T> { public T data; // 数据 public int curs

  • C语言单链表实现方法详解

    本文实例讲述了C语言单链表实现方法.分享给大家供大家参考,具体如下: slist.h #ifndef __SLIST_H__ #define __SLIST_H__ #include<cstdio> #include<malloc.h> #include<assert.h> typedef int ElemType; typedef struct Node { //定义单链表中的结点信息 ElemType data; //结点的数据域 struct Node *next

  • Go语言单链表实现方法

    本文实例讲述了Go语言单链表实现方法.分享给大家供大家参考.具体如下: 1. singlechain.go代码如下: 复制代码 代码如下: ////////// //单链表 -- 线性表 package singlechain //定义节点 type Node struct {     Data int     Next *Node } /* * 返回第一个节点 * h 头结点  */ func GetFirst(h *Node) *Node {     if h.Next == nil {  

  • c语言_构建一个静态二叉树实现方法

    第一.树的构建 定义树结构 struct BTNode { char data; struct BTNode* pLChild; struct BTNode* pRChild; }; 静态方式创建一个简单的二叉树 struct BTNode* create_list() { struct BTNode* pA = (struct BTNode*)malloc(sizeof(BTNode)); struct BTNode* pB = (struct BTNode*)malloc(sizeof(BT

  • C语言深入讲解链表的使用

    目录 一.链表的概念 二.链表的分类 1. 单向或者双向链表 2. 带头或者不带头(是否有自带哨兵位头结点) 3. 循环或者非循环链表 4. 无头单向非循环链表和带头双向循环链表 3.链表的实现(代码和注释) 4.链表oj题(小试牛刀) 总结 现实生活中的火车就像一个完整的链表,现在我们来深入理解一下链表这个数据结构. 一.链表的概念 概念:链表是一种物理存储结构上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链 接次序实现的 . 注: 1.从上图中可看出,链式结构在逻辑上是连续

  • PHP实现HTML页面静态化的方法

    随着网站的内容的增多和用户访问量的增多,无可避免的是网站加载会越来越慢,受限于带宽和服务器同一时间的请求次数的限制,我们往往需要在此时对我们的网站进行代码优化和服务器配置的优化. 一般情况下会从以下方面来做优化 动态页面静态化 优化数据库 使用负载均衡 使用缓存 使用CDN加速 现在很多网站在建设的时候都要进行静态化的处理,为什么网站要进行静态化处理呢?我们都知道纯静态网站是所有的网页都是独立的一个html页面,当我们访问的时候不需要经过数据的处理直接就能读取到文件,访问速度就可想而知了,而其对

随机推荐