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
    


  • 相关阅读:
    AUDIT审计的一些使用
    HOW TO PERFORM BLOCK MEDIA RECOVERY (BMR) WHEN BACKUPS ARE NOT TAKEN BY RMAN. (Doc ID 342972.1)
    使用BBED理解和修改Oracle数据块
    Using Class of Secure Transport (COST) to Restrict Instance Registration in Oracle RAC [ID 1340831.1]
    调试利器GDB概念
    第4章 思科IOS
    第3章 ip地址和子网划分
    第2章 TCPIP
    2020年阅读过的黑客资源推荐篇
    第1章 计算机网络
  • 原文地址:https://www.cnblogs.com/xusw/p/5205866.html
Copyright © 2011-2022 走看看