首页 > 技术文章 > C#顺序表(数据结构)

xmfdsh 2014-04-29 09:05 原文

xmfdsh我近来心情实在不好,只因为这两天课比较少,然后一下子时间太多,不知道干什么,心情郁闷。。。。。。这是要闹哪样?这都让我一个郁闷了一个晚上。闲来无聊,回顾下之前学的C#数据结构,数据结构的重要性无论是对于哪门语言都是很必要也很重要的,课程中老师教的C语言,然后我自己自学的C#,再自学了C#的数据结构,对比了下,发现C,C++这些有着指针,比较低级点的语言,写起数据结构更加能考验一个人的思维,C#作为一门高级语言,也是有着自己一套数据结构的,这些更深层次的对比等我都学了比较精通再来慢慢对比吧。

附上整个项目的源码:https://files.cnblogs.com/xmfdsh/%E9%A1%BA%E5%BA%8F%E8%A1%A8.rar

今天的主题:顺序表

在计算机内,保存线性表最简单的方式,就是把表中的元素一个接着一个地放进顺序的存储单元,这就是线性表的顺序存储。线性表的顺序存储是指在内存中用一块地址连续的空间一次存放线性表的数据元素,用这种方式存储的线性表叫顺序表。

 

由于只考虑到线性表的基本操作,所以以C#接口的形式表示线性表,接口中的方法成员表示基本操作,为了使线性表对任何数据类型都使用,数据元素的类型使用泛型的类型参数

线性表的接口如下表述:

public interface IListDS<T>
    {
        //求长度
        int GetLength();
        //清空
        void Clear();
        //判断线性表是否为空
        bool IsEmpty();
        //判断线性表是否为满
        bool IsFull();
        //附加操作
        void Append(T item);
        //插入
        void Insert(T item, int i);
        //删除
        T Delete(int i);
        //取表元
        T GetElem(int i);
        //按值查找
        int Locate(T value);
    }

接下来就是定义一个类来实现这些接口,首先今天讲的既然是顺序表的话,那么我定义一个ListDS类,来实现这些接口,在那之前先在顺序表中定义几个参数,和实现这些参数的属性:

        private int maxsize;//顺序表容量
        private T[] data;//数组,存放数据元素
        private int last;//最后一个元素位置

        //索引器
        public T this[int index]
        {
            get
            {
                return data[index];
            }
            set
            {
                data[index] = value;
            }
        }
        //最后一个数据元素位置
        public int Last
        {
            get
            {
                return last;
            }
        }
        //容量属性
        public int Maxsize
        {
            get
            {
                return maxsize;
            }
            set
            {
                maxsize = value;
            }
        }
        //构造函数
        public ListDS(int size)
        {
            data = new T[size];
            maxsize = size;
            last = -1;
        }

接下来便是实现这些接口了,方法很简单,既然是数组的话,没有指针什么的,就没有什么难度,像之前学C一样很直接的方式:

//---------------------------------------一下实现接口方法------------------------------------
        //获取长度
        public int GetLength()
        {
            return last + 1;
        }
        //清空操作
        public void Clear()
        {
            last = -1;
        }
        //判断是否为空
        public bool IsEmpty()
        {
            if (last == -1)
                return true;
            else
                return false;
        }
        public bool IsFull()
        {
            if (last == maxsize - 1)
                return true;
            else
                return false;
        }
        //顺序表末尾附加新元素操作
        public void Append(T item)
        {
            if(IsFull())
            {
                Console.WriteLine("顺序表已经满");
                return;
            }
            data[++last] = item;
        }
        //在顺序表第i位置插入一个数据元素
        public void Insert(T item, int i)
        {
            if(IsFull())
            {
                Console.WriteLine("顺序表已经满");
                return;
            }
            if(i<1||i>last+2)
            {
                Console.WriteLine("插入位置错误,不允许");
                return;
            }
            if(i==last+2)
            {
                data[++last] = item;
            }
            else
            {
                for(int j=last;j>=i-1;j--)
                {
                    data[j + 1] = data[j];
                }
                data[i - 1] = item;
                last++;
            }
        }
        //删除
        public T Delete(int i)
        {
            T temp = default(T);
            if(IsEmpty())
            {
                Console.WriteLine("集合为空");
                return temp;
            }
            if(i<1||i>last+2)
            {
                Console.WriteLine("删除位置错误,不允许");
                return temp;
            }
            if(i==last+1)
            {
                temp = data[last--];
            }
            else
            {
                temp = data[i - 1];
                for(int j=i;j<=last;j++)
                {
                    data[j-1] = data[j];
                }
                --last;
            }
            return temp;
        }
        //根据id获取数据元
        public T GetElem(int i)
        {
            if(IsEmpty()||(i<1)||(i>last+1))
            {
                Console.WriteLine("获取数据的位置错误,不允许");
                return default(T);
            }
            return data[i - 1];
        }
        //根据数据查找 对应的位置
        public int Locate(T value)
        {
            if(IsEmpty())
            {
                Console.WriteLine("顺序表为空");
                return -1;
            }
            int i = 0;
            for(i=0;i<=last;i++)
            {
                if (value.Equals(data[i]))
                    break;
            }
            if(i>last)
            {
                return -1;
            }
            return i;

        }

接下来整个数据结构就基本实现了,那么那些实现的菜单和测试的方法我就不写了,再做几道经典的题目吧,首先,就是顺序表倒置,很简单,其实就是泛型的T不一样:

//----------------------------------------顺序表扩展方法----------------------------------------------
        /// <summary>
        /// 顺序表倒置
        /// </summary>
        /// <param name="L"></param>
        public void ReverListDS()
        {
            T temp = default(T);
            int len = GetLength();
            for(int i=0;i<=len/2;i++)
            {
                temp = data[i];
                data[i] = data[len - i];
                data[len - 1] = temp;
            }
        }

第二题:按升序 合并两个表(只限int类型),这里还是可以不一定要限制int类型的,有兴趣的可以去尝试一下,我就拿之前C的最简单的int类型来操作

        /// <summary>
        /// 按升序 合并两个表(只限int类型)
        /// </summary>
        /// <param name="La"></param>
        /// <param name="Lb"></param>
        /// <returns></returns>
        public ListDS<int> Merge(ListDS<int> La,ListDS<int> Lb)
        {
            ListDS<int> Lc = new ListDS<int>(La.maxsize + Lb.maxsize);
            int i = 0;
            int j = 0;
            int k = 0;
            //两个表中都有数据元素
            while((i<=(La.GetLength()-1))&&(j<=(Lb.GetLength()-1)))
            {
                if(La[i]<Lb[j])
                {
                    Lc.Append(La[i++]);
                }
                else
                {
                    Lc.Append(Lb[j++]);
                }
            }
            //a表中剩余的元素
            while(i<=(La.GetLength()-1))
            {
                Lc.Append(La[i++]);
            }
            //b表中剩余的元素
            while(j<(Lb.GetLength()-1))
            {
                Lc.Append(Lb[j++]);
            }
            return Lc;
        }


第三题:构造顺序表Lb,只包含La中所有值不相同元素(以int类型为例)

        /// <summary>
        /// 构造顺序表Lb,只包含La中所有值不相同元素(以int类型为例)
        /// </summary>
        /// <param name="La"></param>
        /// <returns></returns>
        public ListDS<int> Purge(ListDS<int> La)
        {
            ListDS<int> Lb = new ListDS<int>(La.Maxsize);
            Lb.Append(La[0]);
            for(int i=0;i<La.GetLength();i++)
            {
                int j = 0;
                for(j=0;j<Lb.GetLength()-1;j++)
                {
                    if(La[i].CompareTo(Lb[j])==0)
                    {
                        break;
                    }
                }
                if(j>=Lb.GetLength()-1)
                {
                    Lb.Append(La[i]);
                }
            }
            return Lb;
        }

好,顺序表就这样完成了,一下子心情大好,在码这些数据结构的时候,xmfdsh一直在思考,不仅仅思考这个数据结构,更多的是为什么今天会如此焦虑,如此慌乱,明明那么多东西要做,那么多东西要学,当时间来的时候,为什么一下子迷茫到不知道学点什么,一个晚上,xmfdsh终于得出了自己的结论,尽管asp.net 的MVC已经算入门,而且很喜欢,但是asp.net的基础还不是很牢固,更应该去好好学习(昨晚一位师兄突然问我asp.net学的怎样,想给我项目的样子),自己都觉得学无止境啊,另外,发现心情不好的时候码一下代码,竟然能有这等效果,该不会我已经屌丝到这种地步了吧,哈哈哈哈,以后每个星期学一种数据结构或者一种算法,就这么决定了。

推荐阅读