C#创建安全的栈(Stack)存储结构
在C#中,用于存储的结构较多,如:DataTable,DataSet,List,Dictionary,Stack等结构,各种结构采用的存储的方式存在差异,效率也必然各有优缺点。现在介绍一种后进先出的数据结构。
谈到存储结构,我们在项目中使用的较多。对于Task存储结构,栈与队列是类似的结构,在使用的时候采用不同的方法。C#中栈(Stack)是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义;堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小。
在C#中,栈通常保存着我们代码执行的步骤。C#中的引用类型存储在栈中,在程序运行的时候,每个线程(Thread)都会维护一个自己的专属线程堆栈。当一个方法被调用的时候,主线程开始在所属程序集的元数据中,查找被调用方法,然后通过JIT即时编译并把结果(一般是本地CPU指令)放在栈顶。CPU通过总线从栈顶取指令,驱动程序以执行下去。
以上对栈这个数据结构进行了一个简单的介绍,现在看一下C#实现栈结构的底层方法:
/// <summary>
/// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 类的新实例,该实例为空并且具有默认初始容量。
/// </summary>
[__DynamicallyInvokable]
public Stack();
/// <summary>
/// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 类的新实例,该实例为空,具有指定的初始容量或默认的初始容量(其中较大的一个)。
/// </summary>
/// <param name="capacity"><see cref="T:System.Collections.Generic.Stack`1"/> 可包含的初始元素数。</param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
[__DynamicallyInvokable]
public Stack(int capacity);
/// <summary>
/// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 类的新实例,该实例包含从指定集合复制的元素并且具有足够的容量来容纳所复制的元素。
/// </summary>
/// <param name="collection">从中复制元素的集合。</param><exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is null.</exception>
[__DynamicallyInvokable]
public Stack(IEnumerable<T> collection);
以上是对stack的部分方法的介绍,由于在操作数据存储的同时,会考虑到线程的安全性。
进程作为操作系统执行程序的基本单位,拥有应用程序的资源,进程包含线程,进程的资源被线程共享,线程不拥有资源。线程分为前台线程和后台线程,通过Thread类新建线程默认为前台线程。当所有前台线程关闭时,所有的后台线程也会被直接终止,不会抛出异常。
接下来看一下ReaderWriterLockSlim类:
/// <summary>
/// 表示用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。
/// </summary>
[__DynamicallyInvokable]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true, Synchronization = true)]
[HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
public class ReaderWriterLockSlim : IDisposable
{
/// <summary>
/// 使用默认属性值初始化 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 类的新实例。
/// </summary>
[__DynamicallyInvokable]
public ReaderWriterLockSlim();
/// <summary>
/// 在指定锁定递归策略的情况下初始化 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 类的新实例。
/// </summary>
/// <param name="recursionPolicy">枚举值之一,用于指定锁定递归策略。</param>
[__DynamicallyInvokable]
public ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy);
/// <summary>
/// 尝试进入读取模式锁定状态。
/// </summary>
/// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入读取的模式。- 或 -当它已经包含写入锁时,当前线程可能不会获取读的锁定。- 或 -递归数将超出该计数器的容量。此限制是很大的应用程序应永远不会遇到它。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public void EnterReadLock();
/// <summary>
/// 尝试进入读取模式锁定状态,可以选择超时时间。
/// </summary>
///
/// <returns>
/// 如果调用线程已进入读取模式,则为 true;否则为 false。
/// </returns>
/// <param name="timeout">等待的间隔;或为 -1 毫秒,表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException">值 <paramref name="timeout"/> 为负数,但它不等于-1 毫秒为单位),这是唯一允许的值为负。- 或 -值 <paramref name="timeout"/> 大于 <see cref="F:System.Int32.MaxValue"/> 毫秒为单位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public bool TryEnterReadLock(TimeSpan timeout);
/// <summary>
/// 尝试进入读取模式锁定状态,可以选择整数超时时间。
/// </summary>
///
/// <returns>
/// 如果调用线程已进入读取模式,则为 true;否则为 false。
/// </returns>
/// <param name="millisecondsTimeout">等待的毫秒数,或为 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException">值 <paramref name="millisecondsTimeout"/> 为负数,但它不是等于 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),这是唯一允许的值为负。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public bool TryEnterReadLock(int millisecondsTimeout);
/// <summary>
/// 尝试进入写入模式锁定状态。
/// </summary>
/// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已在任何模式下进入该锁。- 或 -当前线程已进入读取的模式,因此尝试进入锁定状态写模式,则会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public void EnterWriteLock();
/// <summary>
/// 尝试进入写入模式锁定状态,可以选择超时时间。
/// </summary>
///
/// <returns>
/// 如果调用线程已进入写入模式,则为 true;否则为 false。
/// </returns>
/// <param name="timeout">等待的间隔;或为 -1 毫秒,表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入写入模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException">值 <paramref name="timeout"/> 为负数,但它不等于-1 毫秒为单位),这是唯一允许的值为负。- 或 -值 <paramref name="timeout"/> 大于 <see cref="F:System.Int32.MaxValue"/> 毫秒为单位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public bool TryEnterWriteLock(TimeSpan timeout);
/// <summary>
/// 尝试进入写入模式锁定状态,可以选择超时时间。
/// </summary>
///
/// <returns>
/// 如果调用线程已进入写入模式,则为 true;否则为 false。
/// </returns>
/// <param name="millisecondsTimeout">等待的毫秒数,或为 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入写入模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException">值 <paramref name="millisecondsTimeout"/> 为负数,但它不是等于 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),这是唯一允许的值为负。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public bool TryEnterWriteLock(int millisecondsTimeout);
/// <summary>
/// 尝试进入可升级模式锁定状态。
/// </summary>
/// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已在任何模式下进入该锁。- 或 -当前线程已进入读取的模式,因此尝试进入可升级模式将有死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public void EnterUpgradeableReadLock();
/// <summary>
/// 尝试进入可升级模式锁定状态,可以选择超时时间。
/// </summary>
///
/// <returns>
/// 如果调用线程已进入可升级模式,则为 true;否则为 false。
/// </returns>
/// <param name="timeout">等待的间隔;或为 -1 毫秒,表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入可升级模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException">值 <paramref name="timeout"/> 为负数,但它不等于-1 毫秒为单位),这是唯一允许的值为负。- 或 -值 <paramref name="timeout"/> 大于 <see cref="F:System.Int32.MaxValue"/> 毫秒为单位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public bool TryEnterUpgradeableReadLock(TimeSpan timeout);
/// <summary>
/// 尝试进入可升级模式锁定状态,可以选择超时时间。
/// </summary>
///
/// <returns>
/// 如果调用线程已进入可升级模式,则为 true;否则为 false。
/// </returns>
/// <param name="millisecondsTimeout">等待的毫秒数,或为 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入可升级模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException">值 <paramref name="millisecondsTimeout"/> 为负数,但它不是等于 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),这是唯一允许的值为负。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
[__DynamicallyInvokable]
public bool TryEnterUpgradeableReadLock(int millisecondsTimeout);
/// <summary>
/// 减少读取模式的递归计数,并在生成的计数为 0(零)时退出读取模式。
/// </summary>
/// <exception cref="T:System.Threading.SynchronizationLockException">在读取模式中,当前线程不已进入该锁。</exception>
[__DynamicallyInvokable]
public void ExitReadLock();
/// <summary>
/// 减少写入模式的递归计数,并在生成的计数为 0(零)时退出写入模式。
/// </summary>
/// <exception cref="T:System.Threading.SynchronizationLockException">当前线程不已进入写入模式的锁定。</exception>
[__DynamicallyInvokable]
public void ExitWriteLock();
/// <summary>
/// 减少可升级模式的递归计数,并在生成的计数为 0(零)时退出可升级模式。
/// </summary>
/// <exception cref="T:System.Threading.SynchronizationLockException">当前线程不已进入可升级模式的锁定。</exception>
[__DynamicallyInvokable]
public void ExitUpgradeableReadLock();
/// <summary>
/// 释放 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 类的当前实例所使用的所有资源。
/// </summary>
/// <exception cref="T:System.Threading.SynchronizationLockException"><see cref="P:System.Threading.ReaderWriterLockSlim.WaitingReadCount"/> 是大于零。- 或 -<see cref="P:System.Threading.ReaderWriterLockSlim.WaitingUpgradeCount"/> 是大于零。- 或 -<see cref="P:System.Threading.ReaderWriterLockSlim.WaitingWriteCount"/> 是大于零。</exception><filterpriority></filterpriority>
[__DynamicallyInvokable]
public void Dispose();
/// <summary>
/// 获取一个值,该值指示当前线程是否已进入读取模式的锁定状态。
/// </summary>
///
/// <returns>
/// 如果当前线程已进入读取模式,则为 true;否则为 false。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public bool IsReadLockHeld { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取一个值,该值指示当前线程是否已进入可升级模式的锁定状态。
/// </summary>
///
/// <returns>
/// 如果当前线程已进入可升级模式,则为 true;否则为 false。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public bool IsUpgradeableReadLockHeld { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取一个值,该值指示当前线程是否已进入写入模式的锁定状态。
/// </summary>
///
/// <returns>
/// 如果当前线程已进入写入模式,则为 true;否则为 false。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public bool IsWriteLockHeld { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取一个值,该值指示当前 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象的递归策略。
/// </summary>
///
/// <returns>
/// 枚举值之一,用于指定锁定递归策略。
/// </returns>
[__DynamicallyInvokable]
public LockRecursionPolicy RecursionPolicy { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取已进入读取模式锁定状态的独有线程的总数。
/// </summary>
///
/// <returns>
/// 已进入读取模式锁定状态的独有线程的数量。
/// </returns>
[__DynamicallyInvokable]
public int CurrentReadCount { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取当前线程进入读取模式锁定状态的次数,用于指示递归。
/// </summary>
///
/// <returns>
/// 如果当前线程未进入读取模式,则为 0(零);如果线程已进入读取模式但却不是以递归方式进入的,则为 1;或者如果线程已经以递归方式进入锁定模式 n - 1 次,则为 n。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public int RecursiveReadCount { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取当前线程进入可升级模式锁定状态的次数,用于指示递归。
/// </summary>
///
/// <returns>
/// 如果当前线程没有进入可升级模式,则为 0;如果线程已进入可升级模式却不是以递归方式进入的,则为 1;或者如果线程已经以递归方式进入可升级模式 n - 1 次,则为 n。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public int RecursiveUpgradeCount { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取当前线程进入写入模式锁定状态的次数,用于指示递归。
/// </summary>
///
/// <returns>
/// 如果当前线程没有进入写入模式,则为 0;如果线程已进入写入模式却不是以递归方式进入的,则为 1;或者如果线程已经以递归方式进入写入模式 n - 1 次,则为 n。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public int RecursiveWriteCount { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取等待进入读取模式锁定状态的线程总数。
/// </summary>
///
/// <returns>
/// 等待进入读取模式的线程总数。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public int WaitingReadCount { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取等待进入可升级模式锁定状态的线程总数。
/// </summary>
///
/// <returns>
/// 等待进入可升级模式的线程总数。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public int WaitingUpgradeCount { [__DynamicallyInvokable] get; }
/// <summary>
/// 获取等待进入写入模式锁定状态的线程总数。
/// </summary>
///
/// <returns>
/// 等待进入写入模式的线程总数。
/// </returns>
/// <filterpriority></filterpriority>
[__DynamicallyInvokable]
public int WaitingWriteCount { [__DynamicallyInvokable] get; }
}
以上是对Stack和线程的相关知识的浅述,现在介绍一下线程安全的Stack:
/// <summary>
/// 表示对象的后进先出线程安全集合(栈结构)
/// </summary>
/// <typeparam name="T"></typeparam>
public class TStack<T> : IEnumerable<T>, ICollection
{
/// <summary>
/// 内部堆栈
/// </summary>
private readonly Stack<T> _mStack; /// <summary>
/// 锁访问堆栈(用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。)
/// </summary>
private readonly ReaderWriterLockSlim _lockStack = new ReaderWriterLockSlim(); /// <summary>
/// 仅用于SyncRoot属性
/// </summary>
private readonly object _objSyncRoot = new object(); // Variables
/// <summary>
/// 初始化一个新的实例 <see cref="TStack{T}"/> class.
/// </summary>
public TStack()
{
_mStack = new Stack<T>();
} /// <summary>
/// 初始化一个新的实例 <see cref="TStack{T}"/> class.
/// </summary>
/// <param name="col">
/// 开始集合
/// </param>
public TStack(IEnumerable<T> col)
{
_mStack = new Stack<T>(col);
} // Init
/// <summary>
/// 获取枚举器
/// </summary>
public IEnumerator<T> GetEnumerator()
{
Stack<T> localStack = null; // 初始化枚举器
_lockStack.PerformUsingReadLock(() =>
{
// 创建一个m_tlist副本
localStack = new Stack<T>(_mStack);
}); // 获取枚举器
foreach (T item in localStack)
yield return item;
} /// <summary>
/// 获取枚举器
/// </summary>
IEnumerator IEnumerable.GetEnumerator()
{
Stack<T> localStack = null; // 初始化枚举器
_lockStack.PerformUsingReadLock(() =>
{
// 创建一个m_TList的副本
localStack = new Stack<T>(_mStack);
}); // 获取枚举器
foreach (T item in localStack)
yield return item;
} /// <summary>
/// 复制到一个数组
/// </summary>
/// <param name="array"></param>
/// <param name="index"></param>
public void CopyTo(Array array, int index)
{
_lockStack.PerformUsingReadLock(() => _mStack.ToArray().CopyTo(array, index));
} /// <summary>
///堆栈中的项目数
/// </summary>
public int Count
{
get
{
return _lockStack.PerformUsingReadLock(() => _mStack.Count);
}
} /// <summary>
/// 总为真
/// </summary>
public bool IsSynchronized
{
get { return true; }
} /// <summary>
///同步根
/// </summary>
public object SyncRoot
{
get { return _objSyncRoot; }
} /// <summary>
///清除集合
/// </summary>
public void Clear()
{
_lockStack.PerformUsingWriteLock(() => _mStack.Clear());
} // Clear
/// <summary>
///如果项目在堆栈中,则为true
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool Contains(T item)
{
return _lockStack.PerformUsingReadLock(() => _mStack.Contains(item));
} // 包含
/// <summary>
/// 返回堆栈中的顶部项,而不从堆栈中删除它
/// </summary>
/// <returns></returns>
public T Peek()
{
return _lockStack.PerformUsingReadLock(() => _mStack.Peek());
} // Peek
/// <summary>
///删除并返回堆栈中的顶部项目
/// </summary>
/// <returns></returns>
public T Pop()
{
return _lockStack.PerformUsingWriteLock(() => _mStack.Pop());
} // Pop
/// <summary>
/// 将一个项目插入堆栈
/// </summary>
/// <param name="item"></param>
public void Push(T item)
{
_lockStack.PerformUsingWriteLock(() => _mStack.Push(item));
} // Push
/// <summary>
///将堆栈转换为数组
/// </summary>
/// <returns></returns>
public T[] ToArray()
{
return _lockStack.PerformUsingReadLock(() => _mStack.ToArray());
} // ToArray
/// <summary>
/// 将容量设置为堆栈中实际的元素数量
/// </summary>
public void TrimExcess()
{
_lockStack.PerformUsingWriteLock(() => _mStack.TrimExcess());
}
}
以上的操作方法继承了IEnumerable<T>, ICollection两个接口。有兴趣的,可以对IEnumerable<T>, ICollection两个接口进行细致的了解。
C#创建安全的栈(Stack)存储结构的更多相关文章
- C#创建安全的字典(Dictionary)存储结构
在上面介绍过栈(Stack)的存储结构,接下来介绍另一种存储结构字典(Dictionary). 字典(Dictionary)里面的每一个元素都是一个键值对(由二个元素组成:键和值) 键必须是唯一的,而 ...
- 栈的存储结构和常见操作(c 语言实现)
俗话说得好,线性表(尤其是链表)是一切数据结构和算法的基础,很多复杂甚至是高级的数据结构和算法,细节处,除去数学和计算机程序基础的知识,大量的都在应用线性表. 一.栈 其实本质还是线性表:限定仅在表尾 ...
- 栈的存储结构的实现(C/C++实现)
存档 #include "iostream.h" #include <stdlib.h> #define max 20 typedef char elemtype; # ...
- 数据结构11: 栈(Stack)的概念和应用及C语言实现
栈,线性表的一种特殊的存储结构.与学习过的线性表的不同之处在于栈只能从表的固定一端对数据进行插入和删除操作,另一端是封死的. 图1 栈结构示意图 由于栈只有一边开口存取数据,称开口的那一端为“栈顶”, ...
- C语言解释器的实现--存储结构(一)
目录: 1. 内存池 2. 栈 3. Hash表 1.内存池 在一些小的程序里,没什么必要添加内存管理模块在里面.但是对于比较复杂的代码,如果需要很多的内存操作,那么加入自己的内存管理是有必要的.至 ...
- Java栈之链式栈存储结构实现
一.链栈 采用单链表来保存栈中所有元素,这种链式结构的栈称为链栈. 二.栈的链式存储结构实现 package com.ietree.basic.datastructure.stack; /** * 链 ...
- C++编程练习(4)----“实现简单的栈的链式存储结构“
如果栈的使用过程中元素数目变化不可预测,有时很小,有时很大,则最好使用链栈:反之,如果它的变化在可控范围内,使用顺序栈会好一些. 简单的栈的链式存储结构代码如下: /*LinkStack.h*/ #i ...
- Java栈之顺序栈存储结构实现
一.栈的基本定义 栈是一种数据结构,它代表一种特殊的线性表,这种线性表只能在固定一端(通常认为是线性表的尾端)进行插入.删除操作的特殊线性表,通常就是在线性表的尾端进行插入.删除操作. 二.顺序栈的实 ...
- iOS数据存储类型 及 堆(heap)和栈(stack)
iOS数据存储类型 及 堆(heap)和栈(stack) 一般认为在c中分为这几个存储区: 1栈 -- 由编译器自动分配释放. 2堆 -- 一般由程序员分配释放,若程序员不释放,程序结束时可能由O ...
随机推荐
- scala - multiple overloaded alternatives of method bar define default arguments
同名同位置默认参数不能overload def bar(i:Int,s:String="a"){} def bar(i:String,s:String="b") ...
- Google Protocol Buffer开发环境搭建注意事项
PB的安装配置基本上依照网上的教程做就没什么问题:有一点要注意到是当遇到libcmt.lib或msvcrt.lib等lib库与PB中的库冲突时,一定要检查工程的编译方式完全一致,整个项目当中都要注意这 ...
- 四、jquery中的事件与应用
当用户浏览页面时,浏览器会对页面代码进行解释或编译--这个过程实质上是通过时间来驱动的,即页面在加载时,执行一个Load事件,在这个事件中实现浏览器编译页面代码的过程.时间无论在页面元素本身还是在元素 ...
- min.js反压缩
给个网址自己体会.. http://jsbeautifier.org/ 当需要修改min.js中的代码时,把min.js文件ctrl+c ctrl+v扔到上面的网页里,点击beautify 即可
- Edge.js:让.NET和Node.js代码比翼齐飞
通过Edge.js项目,你可以在一个进程中同时运行Node.js和.NET代码.在本文中,我将会论述这个项目背后的动机,并描述Edge.js提供的基本机制.随后将探讨一些Edge.js应用场景,它在这 ...
- 企业IT管理员IE11升级指南【3】—— IE11 新的GPO设置
企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...
- 开发OpenWrt路由器上LuCI的模块
[题外话] 学校里最近改造了校园网,要求必须用iNode验证,万幸的是路由器能刷OpenWrt,并且OpenWrt上有好多iNode认证的开源项目,比如njit8021xclient(以下简称njit ...
- Mac下配置Apache服务
这篇文章主要是针对Mac用户,第一次搭建本地开发环境的同学,已经搭建过的同学可以忽略. Mac自带的Apache还是XAMPP? That is a question. 其实自带的apache也够用了 ...
- css水平居中那点事
昨晚深夜写了css垂直居中那点事,今晚该写他的兄弟篇:css水平居中那点事了..…^^ 其实本来这两个可以连在一起写,可是为了不要搞混,为了让思路更清晰,最后决定还是分开来些比较好...这样以后也有利 ...
- DDN - Digital Data Network
DDN(Digital Data Network,数字数据网)是一种利用光纤.数字微波或卫星等数字传输通道和数字交叉复用设备组成的数字数据传输网.它可以为用户提供各种速率的高质量数字专用电 数字数据网 ...