十月份就要考数据结构了,为了这次考试能顺利通过。同时数据结构在开发过程中也是相当重要的,但是以前从来就没有系统地学习过。所以正好借此机会好好地学习下数据结构,一方面是为了通过考试,另一方面也把数据结构和算法这一块的基础打牢一点,真是一举两得啊。

我打算把这一部分写成一个系列,分为C#和C语言两个版本,每周发布两篇。从线性表开始,这一篇主要总结线性表之顺序表的相关操作,主要分以下几个部分来总结。

1,什么是线性表?
2,线性表的两种存储结构?
3,顺序表的存储结构表示? 
4,顺序表的常见操作和代码实现?

1,什么是线性表

线性表就是关系中的一对一的关系,如果是一对多就用树来表示,如果多对多就用网状来表示。

线性表具有以下四个特征:

1> 有且只有一个“首”元素
2> 有且只有一个“尾”元素
3> 除“首”元素外,其余元素都有唯一的后继元素。
4> 除“尾”元素外,其余元素都有唯一的前驱元素。

2,线性表的两种存储结构

1> 顺序表,即线性表用顺序存储结构保存数据,数据是连续的。这一篇文章总结的就是顺序表
2> 链表,即线性表用链式存储结构保存数据,数据不连续。

3,顺序表的存储结构表示

ds05

注:C#和C语言中的数组下标都是从0开始的。

4,顺序表的常见操作和代码实现

顺序表主要有以下常见操作,我们一般用数组来保存数据

1,初始化

思路:将数组的长度length设为0,时间复杂度为O(1)。

2,求顺序表的长度

思路:获取数组的length值,时间复杂度为O(1)。

3,插入元素

思路:分两种情况,一种是插入位置在数组的末尾,这种情况与添加元素相同。另一种情况是插入位置在数组的开始,这时候被插入元素的后续元素都要依次向后移动一位,也就是说整个数组都会移动,所以时间复杂度为O(n)。

4,删除元素

思路:同样分两种情况,一种是删除位置在数组的末尾,不用移动任何元素,因此时间复杂度为O(1);另一种情况是删除位置在数组的开始,这时被删除元素的后续元素都要依次向前移动一位,因此时间复杂度为O(n)。

5,按序号查找元素

思路:因为顺序表的存储地址是连续的,所以第n个元素的地址公式为:(n-1)*单元存储长度,不用移动任何元素,因此时间复杂度为O(1)。

6,按关键字查找元素

思路:一般用for循环,调用IComparable接口的CompareTo()方法去比较,因此时间复杂度为O(n)。

项目结构:

ds01

实现代码:

C#版

namespace DS.Model
{
    /// <summary>
    /// 学生实体
    /// </summary>
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

namespace DS.BLL
{
    /// <summary>
    /// 顺序表操作业务逻辑类
    /// </summary>
    public class SeqListBLL
    {
        /// <summary>
        /// 初始化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="seqListType"></param>
        public static void InitSeqList<T>(SeqListType<T> seqList)
        {
            seqList.ListLen = 0;
        }

        /// <summary>
        /// 获取顺序表的长度
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="seqList"></param>
        /// <returns></returns>
        public static int GetSeqListLen<T>(SeqListType<T> seqList)
        {
            return seqList.ListLen;
        }

        /// <summary>
        /// 插入元素(在第n个元素之前的位置插入新元素)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="seqList"></param>
        /// <param name="n"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool Insert<T>(SeqListType<T> seqList, int n, T data)
        {
            //检查数组是否已满
            if (seqList.ListLen >= seqList.MaxSize) return false;

            //检查n的位置是否超出范围
            if (n < 1 || n > seqList.ListLen + 1) return false;

            //若插入数据位置不在表尾
            if (n <= seqList.ListLen)
            {
                //将要插入位置之后元素依次向后移动一位
                for (int i = seqList.ListLen - 1; i >= n-1; i--)
                {
                    seqList.ListData[i + 1] = seqList.ListData[i];
                }
            }

            //将数据插入到位置为n的位置并将数组的长度加1
            seqList.ListData[n-1] = data;
            seqList.ListLen++;
            return true;
        }

        /// <summary>
        /// 删除元素(删除第n个元素)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="seqList"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static bool Delete<T>(SeqListType<T> seqList, int n)
        {
            //判断数组是否为空
            if (seqList.ListLen == 0) return false;

            //判断n的位置是否合法
            if (n < 1 || n > seqList.ListLen) return false;

            //如果删除不是最后位置
            if (n < seqList.ListLen)
            {
                //将删除位置后继元素依次前移
                for (int i = n; i < seqList.ListLen; i++)
                {
                    seqList.ListData[i-1] = seqList.ListData[i];
                }
            }

            //表长减1
            seqList.ListLen--;
            return true;
        }

        /// <summary>
        /// 查找第n个元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="seqList"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static T GetDataByIndex<T>(SeqListType<T> seqList, int n)
        { 
            //检查位置是否超出范围
            if(n<1||n>seqList.ListLen) return default(T);
            return seqList.ListData[n-1];
        }

        /// <summary>
        /// 按关键字查找元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="W"></typeparam>
        /// <param name="seqList"></param>
        /// <param name="key"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public static T GetDataByKey<T, W>(SeqListType<T> seqList,string key,Func<T,W> where) where W : IComparable
        {
            for (int i = 0; i < seqList.ListLen; i++)
            {
                if (where(seqList.ListData[i]).CompareTo(key) == 0)
                { 
                    return seqList.ListData[i];
                }
            }
            return default(T); //值类型返回0,引用类型返回null
        }
    }

    /// <summary>
    /// 封装顺序表
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SeqListType<T>
    {
        private const int maxSize = 100;
        public int MaxSize { get { return maxSize; } }//表的最大长度

        //初始化长度为100的数组保存数据
        public T[] ListData = new T[maxSize];
        //顺序表的长度
        public int ListLen { get; set; }
    }
}

namespace SeqList.CSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            //定义一个顺序表实例
            SeqListType<Student> seqList = new SeqListType<Student>();

            //初始化
            Console.WriteLine("****************初始化**********************\n");
            SeqListBLL.InitSeqList<Student>(seqList);
            Console.WriteLine("初始化后表的长度为:{0}",SeqListBLL.GetSeqListLen<Student>(seqList));

            //插入数据
            Console.WriteLine("\n****************插入三条数据**********************\n");
            if (!SeqListBLL.Insert<Student>(seqList, 1, new Student { ID = 1, Name = "james", Age = 28 })) Console.WriteLine("插入失败");
            else Console.WriteLine("插入成功");
            if (!SeqListBLL.Insert<Student>(seqList, 1, new Student { ID = 2, Name = "kobe", Age = 33 })) Console.WriteLine("插入失败");
            else Console.WriteLine("插入成功");
            if (!SeqListBLL.Insert<Student>(seqList, 1, new Student { ID = 3, Name = "wade", Age = 31 })) Console.WriteLine("插入失败");
            else Console.WriteLine("插入成功");
            Display(seqList);

            //删除数据
            Console.WriteLine("\n****************删除一条数据**********************\n");
            SeqListBLL.Delete<Student>(seqList,1);
            Console.WriteLine("删除成功");
            Display(seqList);

            //查找元素
            Console.WriteLine("****************查找元素by位置**********************\n");
            Console.WriteLine("查找第{0}个元素",2);
            Student student= SeqListBLL.GetDataByIndex<Student>(seqList,2);
            if (student != null) Console.WriteLine("ID:" + student.ID + ",Name:" + student.Name + ",Age:" + student.Age);
            else Console.WriteLine("没有找到数据");

            //查找元素by关键字
            Console.WriteLine("****************查找元素by关键字**********************\n");
            Console.WriteLine("查找关键字为{0}的元素", "kobe");
            Student student1 = SeqListBLL.GetDataByKey<Student, string>(seqList,"kobe",p=>p.Name);
            if (student1 != null) Console.WriteLine("ID:" + student1.ID + ",Name:" + student1.Name + ",Age:" + student1.Age);
            else Console.WriteLine("没有找到数据");

            //获取表的长度
            Console.WriteLine("****************获取表的当前长度**********************\n");
            int currentLen= SeqListBLL.GetSeqListLen<Student>(seqList);
            Console.WriteLine("当前表中有{0}个元素", currentLen);
            Display(seqList);

            Console.ReadKey();
        }

        /// <summary>
        /// 显示数据
        /// </summary>
        /// <param name="seqList">顺序表对象</param>
        private static void Display(SeqListType<Student> seqList)
        {
            Console.WriteLine("****************展示数据**********************");
            if (seqList == null || seqList.ListLen == 0)
            {
                Console.WriteLine("没有数据");
                return;
            }

            for (int i = 0; i < seqList.ListLen; i++)
            {
                Console.WriteLine("ID:" + seqList.ListData[i].ID + ",Name:" + seqList.ListData[i].Name + ",Age:" + seqList.ListData[i].Age);
            }
        }
    }
}

运行结果:

ds03

C语言版

/*包含头文件*/
#include "stdio.h"
#include "stdlib.h"   
#include "io.h"
#include "math.h" 
#include "time.h"

/*定义常量,类似于C#中的const*/
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20

/*定义类型的同义字*/
typedef int Status;
typedef int ElemType;
typedef struct //定义顺序表
{
    ElemType data[MAXSIZE];
    int length;
}SeqList;


/*初始化*/
Status InitSeqList(SeqList *seqList) //*L表示指向顺序表SeqList的指针
{
    seqList->length=0;
    return OK;
}

/*求顺序表的长度*/
int GetSeqListLen(SeqList *seqList)
{
    return seqList->length;
}

/*插入元素(在第n个元素之前的位置插入新元素)*/
Status Insert(SeqList *seqList,int n,ElemType e)
{
    int k;

    //检查数组是否已满
    if (seqList->length>=MAXSIZE) return ERROR;

    //检查n的位置是否超出范围
    if (n<1||n>seqList->length+1) return ERROR;

    //若插入数据位置不在表尾
    if (n<=seqList->length)
    {
        //将要插入位置之后元素依次向后移动一位
        for (k=seqList->length-1;k>=n-1;k--)
        {
            seqList->data[k+1]=seqList->data[k];
        }
    }

    //将新元素插入到腾出的位置,并将表长加1
    seqList->data[n-1]=e;
    seqList->length++;
    return OK;
}

/*删除元素(删除第n个元素)*/
Status Delete(SeqList *seqList,int n,ElemType *e)
{
    int k;

    //判断数组是否为空
    if (seqList->length==0) return ERROR;

    //判断n的位置是否合法
    if (n<1||n>seqList->length) return ERROR;

    *e=seqList->data[n-1];

    //如果删除不是最后位置
    if (n<seqList->length)
    {
        //将删除位置后继元素依次前移
        for (k=n;k<seqList->length;k++)
        {
            seqList->data[k-1]=seqList->data[k];
        }
    }

    //表长减1
    seqList->length--;
    return OK;
}

/*查找第n个元素*/
int GetDataByIndex(SeqList *seqList,int n)
{
    //检查位置是否超出范围
    if (n<1||n>seqList->length) return ERROR;
    return seqList->data[n-1];
}

/*打印结果*/
void Display(SeqList *seqList)
{
    int i;
    printf("\n********展示数据********\n");
    for (i=0;i<seqList->length;i++)
    {
        Visit(seqList->data[i]);
    }
    printf("\n");
}

Status Visit(ElemType c)
{
    printf("%d\n",c);
    return OK;
}


void main()
{
    //声明变量
    SeqList seqList; //创建顺序表
    int j,k;
    Status i;
    ElemType elem;

    printf("\n*****************初始化************************\n");
    i=InitSeqList(&seqList);//&表示地址
    printf("初始化后表的长度为:%d\n",seqList.length);

    printf("\n*****************插入五条数据************************\n");
    for (j=1;j<=5;j++)
    {
        i=Insert(&seqList,1,j);//在表头依次插入1~5
    }
    Display(&seqList);
    
    printf("\n*****************删除一条数据************************\n");
    i=Delete(&seqList,1,&elem);
    if (i==OK) printf("删除成功\n");
    Display(&seqList);

    printf("\n*****************查找元素by位置************************\n");
    k=GetDataByIndex(&seqList,2);
    printf("第2个元素为%d\n",k);

    printf("\n*****************获取表的当前长度************************\n");
    k=GetSeqListLen(&seqList);
    printf("当前表中有%d个元素\n",k);

    getchar();
}

运行结果:

ds04

posted on 2013-07-09 23:00  永远的麦子  阅读(6080)  评论(1编辑  收藏  举报