• 数据结构和算法系列1 线性表之顺序表


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

    我打算把这一部分写成一个系列,分为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("****************初始化**********************
    ");
                SeqListBLL.InitSeqList<Student>(seqList);
                Console.WriteLine("初始化后表的长度为:{0}",SeqListBLL.GetSeqListLen<Student>(seqList));
    
                //插入数据
                Console.WriteLine("
    ****************插入三条数据**********************
    ");
                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("
    ****************删除一条数据**********************
    ");
                SeqListBLL.Delete<Student>(seqList,1);
                Console.WriteLine("删除成功");
                Display(seqList);
    
                //查找元素
                Console.WriteLine("****************查找元素by位置**********************
    ");
                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关键字**********************
    ");
                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("****************获取表的当前长度**********************
    ");
                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("
    ********展示数据********
    ");
        for (i=0;i<seqList->length;i++)
        {
            Visit(seqList->data[i]);
        }
        printf("
    ");
    }
    
    Status Visit(ElemType c)
    {
        printf("%d
    ",c);
        return OK;
    }
    
    
    void main()
    {
        //声明变量
        SeqList seqList; //创建顺序表
        int j,k;
        Status i;
        ElemType elem;
    
        printf("
    *****************初始化************************
    ");
        i=InitSeqList(&seqList);//&表示地址
        printf("初始化后表的长度为:%d
    ",seqList.length);
    
        printf("
    *****************插入五条数据************************
    ");
        for (j=1;j<=5;j++)
        {
            i=Insert(&seqList,1,j);//在表头依次插入1~5
        }
        Display(&seqList);
        
        printf("
    *****************删除一条数据************************
    ");
        i=Delete(&seqList,1,&elem);
        if (i==OK) printf("删除成功
    ");
        Display(&seqList);
    
        printf("
    *****************查找元素by位置************************
    ");
        k=GetDataByIndex(&seqList,2);
        printf("第2个元素为%d
    ",k);
    
        printf("
    *****************获取表的当前长度************************
    ");
        k=GetSeqListLen(&seqList);
        printf("当前表中有%d个元素
    ",k);
    
        getchar();
    }

    运行结果:

    ds04

  • 相关阅读:
    计算机组成原理期末第十章【计算部分】
    计算机组成原理期末第六章【计算部分】
    快速傅里叶变换总结
    Graph 题解
    NOI 赛前复习旧题 & 复习知识点计划
    Party 题解
    洛谷 P7054 [NWRRC2015]Graph 题解
    CF1542D Priority Queue 题解
    Codeforces Round #701 (Div. 2) E. Move and Swap
    常微分方程
  • 原文地址:https://www.cnblogs.com/mcgrady/p/3181073.html
Copyright © 2020-2023  润新知