Click here to Skip to main content
15,897,273 members
Articles / Programming Languages / C#

A Skip List in C#

Rate me:
Please Sign up or sign in to vote.
4.94/5 (89 votes)
31 Aug 2003MIT9 min read 204.7K   4.4K   114  
Skip Lists, their Algorithms, and a SkipList class in C#.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
using LSCollections;

namespace SkipListStressTest
{
	/// <summary>
	/// Form for inserting items into the dictionary.
	/// </summary>
	public class InsertForm : System.Windows.Forms.Form
	{
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Button cancelButton;
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

        // Indicates the type of insertion operation to perform.
        public enum Operation { Forward, Reverse, Random };

        // The dictionary used for insertion.
        private IDictionary dic;

        // For shuffling numbers for random insertion.
        private Shuffler shuffler = new Shuffler();

        // The type of insertion operation to perform.
        private Operation op;

        // The time the operation took place.
        private double time = 0.0;

        // Number of items to insert.
        private int numItems;

        // Cancel operation flag.
        private bool cancel = false;

        // Worker thread for performing the insertion operation.
        private Thread workerThread;

        /// <summary>
        /// Initializes an instance of the InsertForm class.
        /// </summary>
        /// <param name="dic">
        /// The dictionary to use for insertion.
        /// </param>
        /// <param name="op">
        /// The type of insertion operation to perform.
        /// </param>
        /// <param name="numItems">
        /// The number of items to insert.
        /// </param>
		public InsertForm(IDictionary dic, Operation op, int numItems)
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

            this.dic = dic;
            this.op = op;
            this.numItems = numItems;
            Load += new EventHandler(OnLoad);  
            CancelButton = cancelButton;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.label1 = new System.Windows.Forms.Label();
            this.cancelButton = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(32, 8);
            this.label1.Name = "label1";
            this.label1.TabIndex = 0;
            this.label1.Text = "Cancel operation";
            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // cancelButton
            // 
            this.cancelButton.Location = new System.Drawing.Point(40, 40);
            this.cancelButton.Name = "cancelButton";
            this.cancelButton.TabIndex = 1;
            this.cancelButton.Text = "Cancel";
            this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
            // 
            // InsertForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(168, 86);
            this.Controls.Add(this.cancelButton);
            this.Controls.Add(this.label1);
            this.Name = "InsertForm";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
            this.Text = "Inserting...";
            this.ResumeLayout(false);

        }
		#endregion

        /// <summary>
        /// Event handler for the Cancel button.
        /// </summary>
        private void cancelButton_Click(object sender, System.EventArgs e)
        {
            // Operation has been cancelled.
            cancel = true;
        }

        /// <summary>
        /// Form is loaded.
        /// </summary>
        private void OnLoad(object sender, EventArgs e)
        {
            // Determine which operation to perform and begin the worker
            // thread accordingly.
            switch(op)
            {
                case Operation.Forward:
                    workerThread = new Thread(new ThreadStart(InsertForward));
                    break;

                case Operation.Reverse:
                    workerThread = new Thread(new ThreadStart(InsertReverse));
                    break;

                case Operation.Random:
                    workerThread = new Thread(new ThreadStart(InsertRandom));
                    break;
            }

            // Begin thread.
            workerThread.Start();
        }

        /// <summary>
        /// Worker thread function for inserting items in forward order.
        /// </summary>
        private void InsertForward()
        {
            // Get current tick count. This will be used to determine the 
            // timing results.
            int startTick = Environment.TickCount;

            // Insert items into the dictionary.
            for(int i = 0; i < numItems && !cancel; i++)
            {
                dic.Add(i, i);
            } 

            // If the operation was not cancelled, calculate time results.
            if(!cancel)
            {            
                time = (double)(Environment.TickCount - startTick) / 1000.0;
                DialogResult = DialogResult.OK;
            }
            // Else indicate that the operation was cancelled.
            else
            {
                DialogResult = DialogResult.Cancel;
            }

            // Close form.
            Close();
        }

        /// <summary>
        /// Worker thread function for inserting items in reverse order.
        /// </summary>
        private void InsertReverse()
        {
            // Get current tick count. This will be used to determine the 
            // timing results.
            int startTick = Environment.TickCount;

            // Insert items into the dictionary.
            for(int i = numItems; i >= 0 && !cancel; i--)
            {
                dic.Add(i, i);
            } 

            // If the operation was not cancelled, calculate time results.
            if(!cancel)
            {            
                time = (double)(Environment.TickCount - startTick) / 1000.0;
                DialogResult = DialogResult.OK;
            }
            // Else indicate that the operation was cancelled.
            else
            {
                DialogResult = DialogResult.Cancel;
            }

            // Close form.
            Close();
        }

        /// <summary>
        /// Worker thread function for inserting items in random order.
        /// </summary>
        private void InsertRandom()
        {
            // Create an array to hold numbers.
            int[] array = new int[numItems];

            // Fill array with numbers.
            for(int i = 0; i < array.Length && !cancel; i++)
            {
                array[i] = i;
            }

            // If the operation has not been cancelled, shuffle the numbers.
            if(!cancel)
            {
                shuffler.Shuffle(array);
            }

            // Get current tick count. This will be used to determine the 
            // timing results.
            int startTick = Environment.TickCount;

            // Insert items into the dictionary.
            for(int i = 0; i < array.Length && !cancel; i++)
            {
                dic.Add(array[i], array[i]);
            }

            // If the operation was not cancelled, calculate time results.
            if(!cancel)
            {            
                time = (double)(Environment.TickCount - startTick) / 1000.0;
                DialogResult = DialogResult.OK;
            }
            // Else indicate that the operation was cancelled.
            else
            {
                DialogResult = DialogResult.Cancel;
            }

            // Close form.
            Close();
        }

        /// <summary>
        /// Time property - how long the operation took.
        /// </summary>
        public double Time
        {
            get
            {
                return time;
            }
        }
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
United States United States
Aside from dabbling in BASIC on his old Atari 1040ST years ago, Leslie's programming experience didn't really begin until he discovered the Internet in the late 90s. There he found a treasure trove of information about two of his favorite interests: MIDI and sound synthesis.

After spending a good deal of time calculating formulas he found on the Internet for creating new sounds by hand, he decided that an easier way would be to program the computer to do the work for him. This led him to learn C. He discovered that beyond using programming as a tool for synthesizing sound, he loved programming in and of itself.

Eventually he taught himself C++ and C#, and along the way he immersed himself in the ideas of object oriented programming. Like many of us, he gotten bitten by the design patterns bug and a copy of GOF is never far from his hands.

Now his primary interest is in creating a complete MIDI toolkit using the C# language. He hopes to create something that will become an indispensable tool for those wanting to write MIDI applications for the .NET framework.

Besides programming, his other interests are photography and playing his Les Paul guitars.

Comments and Discussions