数据结构复习---顺序表和单链表

1.前言:

最近比较浮躁,想学习一门新的技术却总是浅尝辄止,遇到不懂的地方就想跳过去,时间长了,心态就有点崩了。静下心来,去喝了几碗心灵鸡汤。鸡汤博主感动到了我:"无专注,无风景。不要太贪心,一次只做一件事,而且只做最重要的事。".于是乎,我把家里翻了个底朝天,找到了我垫在床底下的《数据结构》这本书,觉得自己是时候静下心来好好复习一下基础了。今天刚看到顺序表和链表,把我的学习心得记录在这里。也希望自己能坚持,老老实实的把这本书复习完。

2.数据结构的重要性:

讲一门知识之前,通常流程都是要是先吹一波这个东西的重要性,数据结构和算法虽然已经被吹上天了,我还是觉得有必要:众所周知,数据结构是计算机专业中最重要的课程之一,可是为什么呢?用处太多难以列举,总结成一句话就是:可以让你的程序跑更快。今天主要一下顺序表和单链表的原理和实现

3.顺序表:

顺序表是最简单,最常用,最基本的数据结构

特点:1.结构中的元素存在1对1的线性关系,这种1对1的关系指的是数据元素之间的关系

    2.位置有先后关系,除第一个位置的元素外,其他位置的元素前面都只有一个数据元素,相反除最后一个位置的数据元素外,其他位置的数据元素后面都只有一个元素。

CLR中的实现:List<T>

 顺序表存储结构:

c#实现顺序表(代码中只实现了顺序表的基本功能,没有去做健壮性处理):

  /// <summary>
    /// 顺序表
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ListDS<T> : IListDS<T>
    {

        #region 初始化--2019年1月6日23:20:11
        /// <summary>
        ///存储数据
        /// </summary>
        private T[] Data;
        /// <summary>
        /// 表示存储了多少数据
        /// </summary>
        private int Count;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="size">数据大小</param>
        public ListDS(int size)
        {
            Data = new T[size];
            Count = 0;
        }
        public ListDS() : this(10)
        {

        }
        #endregion

        #region 索引器--2019年1月6日23:20:06
        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T this[int index] => GetEle(index);
        #endregion

        #region 添加--2019年1月6日23:20:03
        /// <summary>
        /// 添加方法
        /// </summary>
        /// <param name="item">添加的元素</param>
        public void Add(T item)
        {
            if (Count == Data.Length)
            {
                Console.WriteLine("当前顺序表已存满");
                return;
            }
            Data[Count] = item;
            Count++;
        }
        #endregion

        #region 清空--2019年1月6日23:19:58
        /// <summary>
        /// 清空
        /// </summary>
        public void Clear()
        {
            Count = 0;
        }
        #endregion

        #region 插入数据--2019年1月6日23:19:54
        /// <summary>
        /// 插入数据 数组向后移动
        /// </summary>
        /// <param name="item"></param>
        /// <param name="index"></param>
        public void Insert(T item, int index)
        {
            for (int i = Count - 1; i >= index; i--)
            {
                Data[i + 1] = Data[i];
            }
            Data[index] = item;
            Count++;
        }
        #endregion

        #region 删除--2019年1月6日23:19:51
        /// <summary>
        /// 删除 删除数据后 数组从后往前移动
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T Delete(int index)
        {
            T temp = Data[index];
            for (int i =index+1 ; i < Count; i++)
            {
                Data[i - 1] = Data[i];
            }
            Count--;
            return temp;
        }
        #endregion

        #region 根据索引获取顺序表元素--2019年1月6日23:19:46
        /// <summary>
        /// 根据索引获取顺序表元素
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T GetEle(int index)
        {
            //判断元素是否存在
            if (index >= 0 && index <= Count - 1)
            {
                return Data[index];
            }
            return default(T);
        }
        #endregion

        #region 获取数组长度--2019年1月6日23:19:43
        /// <summary>
        /// 获取数组长度
        /// </summary>
        /// <returns></returns>
        public int GetLength()
        {
            return Count;
        }
        #endregion

        #region 是否为空--2019年1月6日23:19:40
        /// <summary>
        /// 是否为空
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return Count == 0;
        }
        #endregion

        #region 根据元素获取索引--2019年1月6日23:19:36
        /// <summary>
        /// 根据元素获取索引
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int Locate(T value)
        {
            for (int i = 0; i < Count-1; i++)
            {
                if (Data[i].Equals(value))
                {
                    return i;
                }
            }
            return -1;
        }
        #endregion
    }

4.链表

顺序表使用地址连续的存储单元顺序存储线性表中的各个数据元素,逻辑上想来的数据元素在物理位置上也相邻,因此,在顺序表中查找任何一个位置上的数据元素非常方便,这是顺序表的有点,BUT,顺序表插入/删除时,需要通过移动数据元素,影响了运行效率,线性表的另外一种存储结构--链式存储(Linkend Storage)这样的线性表叫链表。因此,对链表进行插入和删除时,不需要移动数据元素,但同时也失去了顺序表可随机存储的优点

CLR中的实现:LinkedList<T>

链式存储结构:

c#实现单链表节点:

 /// <summary>
    /// 单链表节点
    /// </summary>
    class Node<T>
    {
        #region 初始化
        public T data;//存储数据
        public Node<T> next;//指针 指向下一个元素
        public Node(T _data)
        {
            this.data = _data;
            next = null;
        }
        public Node(T _data,Node<T> _node)
        {
            this.data = _data;
            next = _node;
        }
        public Node()
        {
            this.data = default(T);
            this.next = null;
        }
        public T Data
        {
            get { return data; }
            set { data = value; }
        }
        public Node<T> Next
        {
            get { return next; }
            set { next = value; }
        }
        #endregion
    }

c#实现单链表:

  /// <summary>
    /// 单链表
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class LinkList<T> : IListDS<T>
    {
        #region 初始化
        /// <summary>
        /// 头节点
        /// </summary>
        private Node<T> _head;

        public LinkList()
        {
            _head = null;
        }
        #endregion

        #region 索引器
        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T this[int index] => GetEle(index);
        #endregion

        #region 添加
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="item"></param>
        public void Add(T item)
        {
            //1.  创建一个新节点
            //2.  如果头节点为空,赋值给头节点 return
            //3.1 如果头节点不为空
            //3.2 创建一个节点指向头节点
            //3.3 循环找到尾节点
            //3.4 新节点放在尾部
            Node<T> newNode = new Node<T>(item);

            if (_head == null)
            {
                _head = newNode;
                return;
            }
            Node<T> temp = _head;
            while (true)
            {
                if (temp.Next != null)
                {
                    temp = temp.Next;
                }
                else
                {
                    break;
                }
            }
            temp.Next = newNode;
        }
        #endregion

        #region 清空
        /// <summary>
        /// 清空
        /// </summary>
        public void Clear()
        {
             //清空头节点,垃圾回收器自动回收所有未引用的对象
            _head = null;
        }
        #endregion

        #region 删除
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T Delete(int index)
        {
            //1.如果是头节点,讲指针指向下一个元素
            //2.如果不是头节点,找到要删除节点的前一个节点和要删除的节点
            //3.将引用指向要删除的节点的后一个节点

            T data = default(T);
            //删除头节点
            if (index == 0)
            {
                 data = _head.Data;
                _head = _head.Next;
                 return data;
            }

            Node<T> temp =_head;
            for (int i = 1; i < index - 1; i++)
            {
                temp = temp.Next;
            }
            Node<T> preNode = temp;//要删除的节点的前一个节点
            Node<T> currentNode = temp.Next;//要删除的节点
            data = currentNode.Data;
            Node<T> nextNode = temp.Next.Next;
            preNode.Next = nextNode;
            return data;
        }
        #endregion

        #region 根据索引访问
        /// <summary>
        /// 根据索引访问
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T GetEle(int index)
        {
            Node<T> temp = _head;
            for (int i = 1; i <=index; i++)
            {
                temp = temp.Next;
            }
            return temp.Data;
        }
        #endregion

        #region 获取长度
        /// <summary>
        /// 获取长度
        /// </summary>
        /// <returns></returns>
        public int GetLength()
        {
            if (_head == null)
            {
                return 0;
            }
            int count = 1;
            Node<T> temp = _head;
            while (true)
            {
                if (temp.Next != null)
                {
                    count++;
                    temp = temp.Next;
                }
                else
                {
                    break;
                }
            }
            return count;
        }
        #endregion

        #region 插入
        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="item">数据</param>
        /// <param name="index">位置</param>
        public void Insert(T item, int index)
        {
            //1.  创建一个新节点
            //2.  如果索引为0(头节点) 赋值给头节点 return
            //3.1 如果不是头节点,找到要插入的节点的前一个节点和要插入的节点
            //3.2 前一个节点指向新节点
            //3.3 新节点指向前一个节点
            Node<T> newNode = new Node<T>(item);
            if (index== 0)
            {
                newNode.Next = _head;
                _head = newNode;
                return;
            }
            Node<T> temp = new Node<T>();
            for (int i = 1; i < index-1; i++)
            {
                temp = temp.Next;
            }
            Node<T> preNode = temp;//要插入的节点的前一个节点
            Node<T> curentNode = temp.Next;//要插入的节点
            preNode.next = newNode;
            newNode.Next = curentNode;
        }
        #endregion

        #region 清空
        /// <summary>
        /// 清空
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return _head == null;
        }
        #endregion

        #region 根据数据访问索引
        /// <summary>
        /// 根据数据访问索引
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int Locate(T value)
        {
            Node<T> temp = _head;
            if (temp.Data == null)
            {
                return -1;
            }
            int index = 0;
            while (true)
            {
                if (temp.Data.Equals(value))
                {
                    return index;
                }
                else
                {
                    if (temp.Next != null)
                    {
                        temp = temp.Next;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            return -1;
        }
        #endregion
    }

原文地址:https://www.cnblogs.com/quebra/p/10231046.html

时间: 2024-11-18 01:34:43

数据结构复习---顺序表和单链表的相关文章

数据结构实验报告-实验一 顺序表、单链表基本操作的实现

实验一    顺序表.单链表基本操作的实现   l  实验目的 1.顺序表 (1)掌握线性表的基本运算. (2)掌握顺序存储的概念,学会对顺序存储数据结构进行操作. (3)加深对顺序存储数据结构的理解,逐步培养解决实际问题的编程能力. l  实验内容 1. 顺序表 1.编写线性表基本操作函数: (1)InitList(LIST *L,int ms)初始化线性表: (2)InsertList(LIST *L,int item,int rc)向线性表的指定位置插入元素: (3)DeleteList1

数据结构----顺序表与单链表(JAVA)

下面为学习顺序表和单链表的一些基本操作函数: 1 public class SeqList<T> extends Object { 2 protected int n; 3 protected Object[] element; 4 5 public SeqList(int length) { 6 this.element = new Object[length]; 7 this.n = 0; 8 } 9 10 public SeqList() { 11 this(64); 12 } 13 1

顺序表与单链表

初学数据结构,对顺序表与单链表的概念与操作有点模模糊糊,为此特地查阅了资料,了解了不少,以下是对他们的总结: 顺序表内存中地址连续,长度不变更,支持随机查找,可以在时间复杂度O(1)内查找元素,适用于大量访问元素而少量增添或删除的程序.链表内存地址非连续,长度可以变化,算法时间复杂度为O(n),适用于需要进行大量增添或删除元素操作,而对访问无需求的程序. 下面来看看他们的基本操作(查找,删除,插入)的区别: 顺序表的查找: int GetElem(Seqlist L,int i,DateType

顺序表与单链表的区别及优缺点

线性表之顺序表与单链表的区别及优缺点 尊重原创 -->原文链接 --> 侵权删 这里比较的是基于C语言实现的顺序表与单链表,与其他语言的实现可能会有差异,但我相信语言是相通的,它们的实现机制应该也差不多. 顺序表描述: 顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构.只要确定了起始位置,表中任一元素的地址都通过下列公式得到:LOC(ai)=LOC(a1)+(i-1)*L 1≤i≤n 其中,L是元素占用存储单元的长度. 单链表描述: 单链表

九、顺序表和单链表的对比分析

1.如何判断某个数据元素是否存在于线性表中? find()操作: 可以为线性表List增加一个查找操作 int find(const T& e)const; 参数:待查找的数据元素 返回值: 大于0:数据元素在线性表中第一次出现的位置 -1:数据元素不存在 针对基础数据类型,首先在顶层父类List中增加一个虚函数virtual int find(const T& e) const = 0;,然后在各子类中实现这个函数 // 顺序表中的实现 SeqList.h int find(const

线性表的链式存储——顺序表和单链表的对比分析

1,线性表两种实现: 1,顺序表: 2,单链表: 2,问题: 1,如何判断某个数据元素是否存在线性表中? 1,遍历线性表: 2,封装这个遍历操作: 3,遗失的操作 - find: 1,可以为线性表(List)增加一个查找操作: 2,int find(const T& e) const; 1,参数: 1,待查找的数据元素: 2,返回值: 1,>= 0:数据元素在线性表中第一次出现的位置: 2,-1:数据元素不存在: 3,遍历中会有相等和不等操作符,当比较对象是类的时候,需要类继承自 Objec

经典数据结构实现与分析:顺序表,单链表,

本博客在在这里重新总结了一下,当前常用的经典数据结构:这里只针对链表,顺序表,简单树和图进行总结:具体实现请参考:https://github.com/yaowenxu/codes/tree/master/数据结构; 本文章,主要讨论数据结构的性质:以及对这些数据结构的性质:主要是用来知识整理与复习: 顺序表:顺序表是指,将元素顺序地存放在一块连续的内存中:元素间的顺序关系由他们的存储顺序自然表示:c++声明一个数组:int a[10]; 即构建了10个int内存大小(40bytes)的顺序表:

数据结构之线性表(顺序表,单链表)——图书管理系统

顺序表: 代码如下: 1 #include<iostream> 2 #include<fstream> 3 #include<string> 4 #include<iomanip> 5 using namespace std; 6 #define OK 1 7 #define ERROR 0 8 #define OVERFLOW -2 9 typedef int Status; 10 typedef int ElemType; 11 12 #define M

数据结构:线性表之单链表

线性表(亦作顺序表)是最基本.最简单.也是最常用的一种数据结构.线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的.线性表有两种存储结构: ①顺序存储结构,即存储单元在一段连续的地址上存储,常见的数组就是顺序存储结构的线性表: ②链式存储结构,即存储单元在不连续的地址上存储.因为其不连续性,除了要存数据元素信息(数据域)外,还要存储它后继元素(结点)的地址(指针域,链).学习链式结构最好将结点结构牢记于心,如下图: 链表的每个结点只含有一个指