zoukankan      html  css  js  c++  java
  • [代码分享]静态链表,接口仿照STL设计,操作未做封装

    很久没有来CSDN,也很久没有写东西了。去年12月在OSCHINA注册了号,发了两段code。这次转过来,以便日后查阅。

    连接:http://www.oschina.net/code/snippet_737017_16964

    这是一段静态链表的实现,其间用到了一种简单的内存管理策略——空闲链表。

    这段代码里的“静态”是一个预先分配好的 node array,实际情况下可能会是一个一次性申请的较大的memory block。

    其实是在这段 node array上维护两个链表,一个used list,一个free list,即代码中的idata,和ifree。

    // 静态链表 的实现
    #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 lase nod 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;
    	}
    }

    完整代码及测试见:http://www.oschina.net/code/snippet_737017_16964

    记得曾经在反《算法导论》的时候好像看到书中提到静态链表的实现问题,当时没有在意,直到去年写下这段代码的时候任然没有详细去看;今天翻出电子版一看,有近两页篇幅描述。

    《算法导论》中的描述还是较为精炼的,文字不多,条理清晰,这里有一副原书中的插图,书中先讲了在没有指针的语言中如何表示指针和对象;


    然后,话锋一转,在这样的情况下“Thus, it is useful to manage the storage of objects not currently used in the linked-list representation so that one can be allocated.”

    然后书中也给出了伪代码:(要是早知道,我也那个夜晚也不用搞到两点了

    ALLOCATE-OBJECT()
     if free = NIL
       then error "out of space"
     else x ← free
       free ← next[x]
       return x
    FREE-OBJECT(x)
    1 next[x] ← free
    2 free ← x
    


  • 相关阅读:
    dede list调用 内容模型 附件
    dedecms list标签调用附加表字段--绝对成功
    织梦系统站点首页、列表、文章页等页面点击数调用方法
    apache include 文件包含引用的方法 报错 [an error occurred while processing this directive]
    windows 2008 中IIS7.0以上如何设置404错误页面
    织梦Fatal error: Call to a member function GetInnerText()
    dedecms清空栏目后,新建ID不从1开始的解决方法
    js禁止
    AngularJs表单验证
    submile 安装,汉化,插件
  • 原文地址:https://www.cnblogs.com/xusw/p/5205866.html
Copyright © 2011-2022 走看看