单链表_单链表基本操作 - CSDN
单链表 订阅
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。 展开全文
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
信息
外文名
Singly Linked List
类    型
数据结构元素
建立过程
申请空间、得到数据、建立链接
中文名
单链表
简    介
地址任意的存储单元存放数据元素
实    质
一种链式存取的数据结构
单链表单链表简介
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。以“结点的序列”表示线性表称作线性链表(单链表),单链表是链式存取的结构。链接方式存储的线性表简称为链表(Linked List)。链表的具体存储表示为:① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。┌───┬───┐│data │next │└───┴───┘data域--存放结点值的数据域next域--存放结点的直接后继的地址(位置)的指针域(链域)链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的,每个结点只有一个链域的链表称为单链表(Single Linked List)。单链表中每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点。链表由头指针唯一确定,单链表可以用头指针的名字来命名。终端结点无后继,故终端结点的指针域为空,即NULL。
收起全文
精华内容
参与话题
  • 单链表的基本操作

    万次阅读 多人点赞 2018-08-26 14:29:35
    链表:一种链式存储的线性表,用一组地址任意的存储单元...单链表的存储结构 typedef int DataType; typedef struct ListNode { DataType _data; //当前节点中所保存的元素 struct ListNode* _pNext; //指向...

    链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称为存储单元为一个节点。
    这里写图片描述

    单链表的存储结构

    typedef int DataType;
    
    typedef struct ListNode
    {
        DataType _data;                 //当前节点中所保存的元素
        struct ListNode* _pNext;    //指向链表中下一个结点
    
    }SLinkList, SListNode;
    链表的分类

    这里写图片描述

    单链表的基本操作

    void PrintSLinkList(SLinkList* pHead);//打印
    void InitSLinkList(SLinkList** ppHead);//初始化
    void DestroySLinkList(SLinkList** ppHead);//销毁
    void PushBack(SLinkList** ppHead, DataType data);//尾部插入
    void PopBack(SLinkList** ppHead);//尾部删除
    void PushFront(SLinkList** ppHead, DataType data);//头部插入
    void PopFront(SLinkList** ppHead);//头部删除
    SLinkList* Find(SLinkList* pHead, DataType data);//查找元素的位置
    void Delete(SLinkList** ppHead, SLinkList* pos);//指定位置删除元素
    void Revome(SLinkList** ppHead, DataType data);//删除第一个出现的指定元素
    void RemoveAll(SLinkList** ppHead, DataType data);//删除出现的所有元素
    int GetLinkListLength(SLinkList* pHead);//计算单链表的长度
    void BubbleSort(SLinkList** ppHead);//冒泡排序

    0.打印
    //打印
    void PrintSLinkList(SLinkList* pHead)
    {
        SLinkList* cur = pHead;
        while (cur)
        {
            printf("%d -> ", cur->_data);
            cur = cur->_pNext;
        }
        printf("NULL\n");
    }
    1.初始化

     初始化就是让指向单链表的指针指向空,因为要改变指针的志向所以需要传指针的地址

    //初始化
    void InitSLinkList(SLinkList** ppHead)
    {
        assert(ppHead);
        *ppHead = NULL;
    }
    2.销毁

     因为单链表都是用malloc开辟的内存空间,所以每次使用结束都要将其释放掉,所以就有一个销毁函数,将所有的结点释放掉,并让指向链表的指针指向空。

    //销毁
    void DestroySLinkList(SLinkList** ppHead)
    {
        SLinkList* cur = *ppHead;
        SLinkList* del = NULL;
    
        assert(ppHead);
    
        while (cur)
        {
            del = cur;
            cur = cur->_pNext;
    
            free(del);
            del = NULL;
        }
        *ppHead = NULL;
    }

    节点的函数

     由于后面的插入会用malloc开辟空间,制作节点,所以在这里提前将我封装的函数写下来

    SLinkList* BuyNode(DataType data)
    {
        SLinkList* p = (SLinkList*)malloc(sizeof(SLinkList));
        //malloc开辟的空间一定要判断成功还是失败
        if (p == NULL)
        {
            perror("BuyNode::malloc");
            return NULL;
        }
        //空间开辟成功,将赋给节点中的数据域,将指针域赋为空指针
        p->_data = data;
        p->_pNext = NULL;
        //返回节点的地址
        return p;
    }
    3.尾部插入
    1.空链表:直接连接,不需要遍历
    2.非空链表:找到最后一个节点,连接
    

     尾部插入,顾名思义就要知道它的尾部在哪里,所以,我们要遍历取找它的尾部,单恋表的最后一个元素没有指向任何元素,所以它指向小孩一个节点的指针指向空,找到后插入。单链表有时是一个空表,需要改变指针的值,所以需要传指针的地址。
    这里写图片描述

    //尾部插入
    void PushBack(SLinkList** ppHead, DataType data)
    {
        SLinkList* NewNode = NULL;
        SLinkList* cur = *ppHead;
    
        assert(ppHead);
    
        NewNode = BuyNode(data);
    
        //1.空链表:直接连接
        if (*ppHead == NULL)
        {
            *ppHead = NewNode;
        }
        //2.非空链表
        else
        {
            //a.找最后一个结点
            while (cur->_pNext)
            {
                cur = cur->_pNext;
            }
            //b.连接
            cur->_pNext = NewNode;
        }
    }
    4.尾部删除
    1.空链表:不能删除,直接结束
    2.只有一个节点:删除,将头指针置空
    3.两个及以上的节点:找到最后一个节点并将倒数第二个节点置空
    
    //尾部删除
    void PopBack(SLinkList** ppHead)
    {
        SLinkList* cur = *ppHead;
        assert(ppHead);
        //1.空链表:不能删除,直接结束
        if (*ppHead == NULL)
        {
            printf("单链表为空,不能删除!!!\n");
            return;
        }
        //2.只有一个元素:删除,并将头结点置空
        else if ((*ppHead)->_pNext == NULL)
        {
            free((*ppHead)->_pNext);
            *ppHead = NULL;
        }
        //3.两个及以上的元素:找最后一个元素,删除
        else
        {
            while (cur->_pNext->_pNext != NULL)
            {
                cur = cur->_pNext;
            }
            free(cur->_pNext);
            cur->_pNext = NULL;
        }
    }

    5.头部插入
    单链表的头部插入都需要改变指向链表指针的指向,所以不分情况可以直接操作
    
    //头部插入
    void PushFront(SLinkList** ppHead, DataType data)
    {
        SLinkList* NewNode = NULL;
        assert(ppHead);
    
        NewNode = BuyNode(data);
    
        NewNode->_pNext = *ppHead;
        *ppHead = NewNode;
    }
    6.头部删除
    单链表为空,不能随其进行删除操作,所以需要分别其为空链表还是非空链表
    
    //头部删除
    void PopFront(SLinkList** ppHead)
    {
        SLinkList* cur = *ppHead;
        assert(ppHead);
        //1.空链表,不能删除
        if (*ppHead == NULL)
        {
            printf("单链表为空,不能删除!!!\n");
            return;
        }
        //2.非空链表
        *ppHead = cur->_pNext;
        free(cur);
        cur = NULL;
    }
    7.查找元素的位置

     从单链表的第一个节点开始,判断当前节点的数据域的值是否与给定的值相等。若相等,则返回该节点的地址,否则继续比较下一个节点,直到链表结束。若节点不存在,则返回空。

    //查找元素的位置
    SLinkList* Find(SLinkList* pHead, DataType data)
    {
        SLinkList* cur = pHead;
        while (cur != NULL)
        {
            if (cur->_data == data)
                break;
            cur = cur->_pNext;
        }
        return cur; //有可能返回空值或所查元素的地址
    }
    8.指定位置删除元素

     遍历单链表,由于要删除指定位置的元素,需要将前一个节点的next指针域指向被删除节点的下一个节点。
    这里写图片描述

    //指定位置删除元素
    void Delete(SLinkList** ppHead, SLinkList* pos)
    {
        SLinkList* cur = *ppHead;
        SLinkList* del = NULL;
        assert(ppHead);
        //空链表
        if (*ppHead == NULL)
            return;
        //要删除位置元素为第一个节点
        if (*ppHead == pos)
            PopFront(ppHead);
        while (cur != NULL && cur->_pNext != pos)
        {
            cur = cur->_pNext;
        }
        if (cur != NULL)
        {
            cur->_pNext = cur->_pNext->_pNext;
            free(pos);
            pos = NULL;
        }
    }
    9.删除第一个出现的元素

     找到第一个指定元素出现的元素的前一个节点,指向被删除元素的下一个节点。因为是使用malloc开辟的空间,所以要用free()释放掉。
    这里写图片描述

    //删除第一个出现的指定元素
    void Revome(SLinkList** ppHead, DataType data)
    {
        SLinkList* cur = *ppHead;
        SLinkList* pre = NULL;
        assert(ppHead);
        //链表为空
        if (*ppHead == NULL)
            PopFront(ppHead);
        //链表非空
        while (cur != NULL)
        {
            if (cur->_data == data)
            {
                //首节点为所删元素
                if (pre == NULL)
                    PopFront(ppHead);   //头删法
                else
                {
                    pre->_pNext = cur->_pNext;
                    free(cur);
                    cur = NULL;
                }
                return;
            }
            pre = cur;
            cur = cur->_pNext;
        }
    }
    10.删除出现的所有元素

    这里写图片描述

    //删除出现的所有元素
    void RemoveAll(SLinkList** ppHead, DataType data)
    {
        SLinkList* cur = *ppHead;
        SLinkList* pre = NULL;
        SLinkList* del = NULL;
        assert(ppHead);
        //空链表
        if (*ppHead == NULL)
            return;
        //非空链表
        while (cur != NULL)
        {
            if (cur->_data == data)
            {
                //要删除的元素是第一个节点
                if (pre == NULL)
                {
                    del = cur;
                    cur = cur->_pNext;
                    *ppHead = cur;
                }
                else
                {
                    //用del指定需要被删除的元素,将被删除元素从链表上取下来
                    del = cur;
                    cur = cur->_pNext;
                    pre->_pNext = cur;
                }
                //删除需要删除的结点
                free(del);
                del = NULL;
            }
            else
            {
                pre = cur;
                cur = cur->_pNext;
            }
        }
    }
    11.计算单链表的长度

     利用count,对链表的结点进行计数。

    //计算单链表的长度
    int GetLinkListLength(SLinkList* pHead)
    {
        SLinkList* cur = pHead;
        int len = 0;
        //空链表
        if (pHead == NULL)
            return 0;
        //非空链表
        while (cur != NULL)
        {
            len++;
            cur = cur->_pNext;
        }
        return len;
    }
    11.冒泡排序

       外循环为链表的长度-1次,设置一个尾结点,外循环每执行一次,尾结点向前移动一步。

    //冒泡排序
    void BubbleSort(SLinkList** ppHead)
    {
        SLinkList* pTail = NULL;    //标记:未排序元素的最后一个元素
        SLinkList* pPre = NULL;
        SLinkList* pCur = NULL;
    
        assert(ppHead);
        //趟数
        while (pTail != *ppHead)
        {
            pPre = *ppHead;
            pCur = *ppHead;
            //单趟
            while (pCur != pTail)
            {
                //升序
                if (pPre->_data > pCur->_data)
                {
                    DataType tmp = pPre->_data;
                    pPre->_data = pCur->_data;
                    pCur->_data = tmp;
                }
                pPre = pCur;
                pCur = pCur->_pNext;
            }
            pTail = pPre;
        }
    }
    12.选择排序
    void SelectsortLinkList(SLinkList *pHead)
    {
        SLinkList *max = pHead;  //最大值指针
        SLinkList *tail = pHead;
        SLinkList *cur = NULL;
        DataType node = 0;
        int length = GetLinkListLength(pHead) - 1;
        //尾结点,tail指向空
        while (tail != NULL)
        {
            tail = tail->_pNext;
        }
        while (length--)
        {
            max = pHead;
            cur = pHead->_pNext;
            while (cur->_pNext != tail)
            {
                //找到链表的最大值
                if (cur->_data > max->_data)
                {
                    max = cur;
                }
                cur = cur->_pNext;
            }
            //比较链表尾结点是不是最大值
            if (cur->_data > max->_data)
            {
                max = cur;
            }
            if (max != cur)
            {
                //交换
                node = max->_data;
                max->_data = cur->_data;
                cur->_data = node;
            }
            tail = cur;
        }
    }
    展开全文
  • 单链表的讲解:单链表的原理,添加、删除元素

    万次阅读 多人点赞 2018-09-16 00:06:42
    单链表及其节点 链表是一系列的存储数据元素的单元通过指针串接起来形成的,因此每个单元至少有两个域, 一个域用于数据元素的存储,另一个域是指向其他单元的指针。 这里具有一个数据域和多个指针域的存储单元通常...

    单链表及其节点

    链表是一系列的存储数据元素的单元通过指针串接起来形成的,因此每个单元至少有两个域,
    一个域用于数据元素的存储,另一个域是指向其他单元的指针。
    这里具有一个数据域和多个指针域的存储单元通常称为 结点(node)

    一种最简单的结点结构如图所示,它是构成单链表的基本结点结构。在结点中数据域用来存储数据元素,
    指针域用于指向下一个具有相同结构的结点。
    因为只有一个指针结点,称为单链表 
     
        
    链表的第一个结点和最后一个结点,分别称为链表的 首结点和 尾结点。
    尾结点的特征是其 next 引用为空(null)。
    链表中每个结点的 next 引用都相当于一个指针,指向另一个结点,
    借助这些 next 引用,我们可以从链表的首结点移动到尾结点。
    在单链表中通常使用 head 引用来指向链表的首结点,由 head 引用可以完成对整个链表中所有节点的访问。

         
        在单链表结构中还需要注意的一点是,由于每个结点的数据域都是一个 Object 类的对象,
        因此,每个数据元素并非真正如图中那样,而是在结点中的数据域通过一个 Object类的对象引用来指向数据元素的。
    与数组类似,单链表中的结点也具有一个线性次序,即如果结点 P 的 next 引用指向结点 S,则 P 就是 S 的直接前驱,S 是 P 的直接后续。
    单链表的一个重要特性就是只能通过前驱结点找到后续结点,而无法从后续结点找到前驱结点。


    单链表的查询、添加、删除操作分析
        查询操作
        在单链表中进行查找操作,只能从链表的首结点开始,通过每个结点的 next 引用来一次访问链表中的每个结点以完成相应的查找操作。
        
    例如需要在单链表中查找是否包含某个数据元素 e,则方法是使用一个循环变量 p,起始时从单链表的头结点开始,
    每次循环判断 p所指结点的数据域是否和 e 相同,如果相同则可以返回 true,否则让p指向下一个节点,继续循环直到链表中所有
    结点均被访问,此时 p 为 null
         

             关键操作:
            1.起始条件:p = head;
            2.结束条件:
                找到:e.equals(p.getData())==true
                未找到  p == null
            3.p指向下一个结点: p  = p.getNext();
            
            缺点:逐个比较,频繁移动指针,导致效率低下
            
            注意:如果要查询第i个元素的值,无法直接定位,也只能从首结点开始逐个移动到第i个结点,效率同样低下。
        添加操作
        在单链表中数据元素的插入,是通过在链表中插入数据元素所属的结点来完成的。
        对于链表的不同位置,插入的过程会有细微的差别。
        中间、末尾的添加过程其实是一样的,关键是在首部添加,会有不同,会改变整个单链表的起始结点。
        
         

            以添加中间结点为例
            1.指明新结点的后继  s.setNext(p.getNext());   或者 s.next = p.next
            2.指明新结点的前驱(其实是指明前驱结点的后继是新结点) p.setNext(s)    或者 p.next = s;
            
        添加节点不需要移动元素,只需要修改元素的指针即可,效率高。
        但是如果需要先查询到添加位置再添加新元素,因为有逐个查询的过程,效率不高。


        删除操作
            类似添加操作
             
             
        
        在使用单链表实现线性表的时候,为了使程序更加简洁,我们通常在单链表的最前面添加一个哑元结点,也称为头结点。
        在头结点中不存储任何实质的数据对象,其 next 域指向线性表中 0 号元素所在的结点,
        可以对空表、非空表的情况以及对首元结点进行统一处理,编程更方便,常用头结点。
        一个带头结点的单链表实现线性表的结构图如图 所示。
         

    单链表的代码实现:

    
    /**
     * 单链表
     * @author Administrator
     *
     */
    public class SingleLinkedList implements List{
    	
    	public Node head = new Node();//只有一个头结点
    	
    	public int size;//默认长度是0,头结点不算
    	
    	public SingleLinkedList(){
    		
    	}
    
    	@Override
    	public int size() {
    		
    		return size;
    	}
    	/**
    	 * 和数组可是不一样了!!!
    	 */
    	@Override
    	public Object get(int i) {
    		return null;
    	}
    
    	@Override
    	public boolean isEmpty() {		
    		return size == 0;
    	}
    
    	@Override
    	public boolean contains(Object e) {		
    		return this.indexOf(e)>=0;
    	}
    
    	@Override
    	public int indexOf(Object e) {
    		Node p = head.getNext();
    		for(int i = 0 ;i<size;i++){
    			//取出当前结点的值
    			Object data = p.getData();
    			//判断是否相同
    			if(e.equals(data)){
    				return i;
    			}
    			//移动指针
    			p = p.getNext();
    		}
    		
    		return -1;
    	}
    
    	@Override  
    	public void add(int i, Object e) {
    		//判断i的范围,提高健壮性
    		if(i<0 || i>size){
    			throw new IndexOutOfBoundsException("索引越界异常:"+i);
    		}
    		//定位到前一个结点
    		Node p = head;
    		for(int j = 0 ;j<i;j++){
    			p = p.getNext();
    		}
    		
    		//创建一个新结点
    		Node s = new Node();
    		s.setData(e);
    		
    		//完成添加操作
    		s.setNext(p.getNext());//指明新结点的后继
    		p.setNext(s);//指明新结点的前驱(其实是指明前驱结点的后继是新结点)
    		
    		//size增1
    		size++;
    	}	
    	
    
    	@Override
    	public void add(Object e) {
    		int i = this.size;
    		this.add(i,e);
    		
    	}
    
    	@Override
    	public boolean addBefore(Object obj, Object e) {
    		return false;
    	}
    
    	@Override
    	public boolean addAfter(Object obj, Object e) {
    		return false;
    	}
    
    	@Override
    	public Object remove(int i) {
    		
    		return null;
    	}
    
    	@Override
    	public boolean remove(Object e) {
    		//先确定前驱结点和要删除结点
    		Node p = head;  
    		Node s = head.getNext();
    		boolean flag = false;//默认该结点不存在
    		while(s!= null ){
    			//判断是否找到
    			if(e.equals(s.getData())){
    				flag = true;
    				break;
    			}
    			//如果没有找到,移动指针到后一个结点
    			p = s;
    			s = s.getNext();			
    		}
    		//如果找到,就删除
    		if(flag){
    			p.setNext(s.getNext());
    			s.setNext(null);
    			s =null;
    		}
    		return flag;
    		
    	}
    
    	@Override
    	public Object replace(int i, Object e) {
    		return null;
    	}
    
    	@Override
    	public String toString() {
    		StringBuilder builder = new StringBuilder("[");
    		Node p = head.getNext();
    		while(p!=null){			
    			//取出结点值
    			Object data = p.getData();
    			//加入StringBuffer
    			builder.append(data+",");
    			//后移一个结点
    			p = p.getNext();
    		}
    		//删除最后的一个逗号
    		if(builder.length()>1){
    			builder.deleteCharAt(builder.length()-1);
    		}
    		builder.append("]");
    		
    		return builder.toString();
    	}
    	
    	
    }
    
    
    	测试类
    public class Test {
    	
    	public static void main(String[] args) {
    		//创建线性顺序表
    		List list = new SingleLinkedList();
    		//向末尾添加元素
    		list.add("11111");
    		list.add("aaaaa");
    		list.add("bbbbb");
    		list.add("33333");
    		list.add("22222");
    		
    		list.add(2, "AAAAA");
    		System.out.println(list.toString());
    		list.remove("AAAAA");
    		System.out.println(list.toString());
    		//进行各种操作验证添加
    //		System.out.println(list.size());
    //		System.out.println(list.isEmpty());
    //		System.out.println(list.contains("AAAAA"));
    //		System.out.println(list.indexOf("22222"));
    //		
    //		System.out.println(list.toString());
    		
    	}
    
    }
    

    作业
    1.提取获取第i结点前一个结点方法:getPreviousNode(int i)
       提取data是e结点前一个结点方法:getPreviousNode(Object e)
       并进行重用
    2.完成SingleLinkedList类没有实现的方法
     

    展开全文
  • 【数据结构】单链表的各种功能实现(C语言)

    万次阅读 多人点赞 2018-09-26 16:19:43
    单链表的存储方式

    链表的分类及存储方式

    单链表

    在这里插入图片描述
    在这里插入图片描述

    双链表

    在这里插入图片描述
    在这里插入图片描述

    双向循环链表

    在这里插入图片描述
    在这里插入图片描述

    创建一个单链表

    //不是链表的结构体
    //链表中一个节点的结构体
    typedef struct SListNode {
    	DataType data; // 值 
    	struct SListNode *Next; // 指向下一个结点 
    } SListNode;
    

    链表要实现的功能

    // 初始化 ,构造一条空的链表
    void SListInit(SListNode **ppFirst);
    
    //打印链表
    void SListInit(SListNode **ppFirst);
    
    // 尾部插入 
    void SListPushBack(SListNode** ppFirst, DataType data);
    
    // 头部插入 
    void SListPushFront(SListNode **ppFirst, DataType data);
    
    // 尾部删除 
    void SListPopBack(SListNode **ppFirst);
    
    // 头部删除 
    void SListPopFront(SListNode **ppFirst);
    
    // 给定结点插入,插入到结点前 
    void SListInsert(SListNode **ppFirst, SListNode *pPos, DataType data);
    
    // 给定结点删除 
    void SListErase(SListNode **ppFirst, SListNode *pPos);
    
    // 按值删除,只删遇到的第一个 
    void SListRemove(SListNode **ppFirst, DataType data);
    
    // 按值删除,删除所有的 
    void SListRemoveAll(SListNode **ppFirst, DataType data);
    
    // 销毁 ,需要销毁每一个节点
    void SListDestroy(SListNode **ppFirst);
    
    // 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL 
    int SListFind(SListNode *pFirst, DataType data);
    

    链表的各种功能具体实现

    链表的初始化

    void SListInit(SListNode **ppFirst)//初始化
    {
    	assert(ppFirst != NULL);
    	*ppFirst = NULL;
    }
    

    打印链表

    //打印链表
    void SListPrint(SListNode *First)
    {
    	for (SListNode*cur = First; cur != NULL; cur = cur->Next)
    	{
    		printf("%d-->", cur->data);
    	}
    	printf("\n");
    	return 0;
    }
    

    尾插

    在这里插入图片描述

    //申请新节点
    static SListNode* CreateNode(DataType data)
    {
    	SListNode*node = (SListNode*)malloc(sizeof(SListNode));
    	node->data = data;
    	node->Next = NULL;
    	return node;
    }
    // 尾部插入 
    void SListPushBack(SListNode** ppFirst, DataType data)
    {
    	assert(ppFirst != NULL);
    	SListNode *node = CreateNode(data);
    	if (*ppFirst == NULL)//判断链表不为空
    	{
    		*ppFirst = node;
    		return;
    	}
    	//找链表中的最后一个节点
    	SListNode* cur = *ppFirst;
    	while (cur->Next != NULL)
    	{
    		cur = cur->Next;
    	}
    	cur->Next = node;//插入新申请的节点
    }
    

    头插

    void SListPushFront(SListNode **ppFirst, DataType data)
    {
    	assert(ppFirst != NULL);
    	SListNode *node = CreateNode(data);
    	node->Next = *ppFirst;
    	*ppFirst = node;
    }
    

    尾删

    在这里插入图片描述

    // 尾部删除 
    void SListPopBack(SListNode **ppFirst)
    {
    	assert(ppFirst != NULL);
    	assert(*ppFirst != NULL);
    	if ((*ppFirst)->Next == NULL)
    	{
    		free(*ppFirst);
    		*ppFirst = NULL;
    		return;
    	}
    	SListNode*cur = *ppFirst;
    	while (cur->Next->Next != NULL)
    	{
    		cur = cur->Next;
    	}
    	free(cur->Next);
    	cur->Next = NULL;
    }
    

    头删

    在这里插入图片描述

    // 头部删除 
    void SListPopFront(SListNode **ppFirst)
    {
    	assert(ppFirst != NULL);
    	assert(*ppFirst != NULL);//链表不是空链表
    	SListNode *first = *ppFirst;
    	*ppFirst = (*ppFirst)->Next;
    	free(first);
    }
    

    给定结点插入,插入到结点前

    在这里插入图片描述

    void SListInsert(SListNode **ppFirst, SListNode *pPos, DataType data)
    {
    	assert(ppFirst != NULL);
    	if (*ppFirst == pPos)
    	{
    		SListPushFront(ppFirst, data);
    		return;
    	}
    	SListNode*newNode = CreateNode(data);
    	SListNode*cur;
    	//找到pos前的一个节点
    	for (cur = *ppFirst; cur->Next != pPos; cur = cur->Next){ }
    	//改变的是字段内的值,而不是指针的值
    	cur->Next = newNode;
    	newNode->Next = pPos;
    }
    

    给定结点删除

    在这里插入图片描述

    // 给定结点删除 
    void SListErase(SListNode **ppFirst, SListNode *pPos)
    {
    	if (*ppFirst == pPos)
    	{
    		SListPopFront(ppFirst);
    		return;
    	}
    	SListNode *cur = *ppFirst;
    	while (cur->Next != pPos)
    	{
    		cur = cur->Next;
    	}
    	cur->Next = pPos->Next;
    	free(pPos);
    }
    

    按值删除,只删遇到的第一个

    // 按值删除,只删遇到的第一个 
    void SListRemove(SListNode **ppFirst, DataType data)
    {
    	SListNode *cur = *ppFirst;
    	SListNode *prev = NULL;
    	assert(ppFirst != NULL);
    	if (*ppFirst == NULL)
    		return;
    	while (cur)
    	{
    		if (cur->data == data)
    		{
    			//删除
    			//1.删除的是第一个节点
    			if (*ppFirst == cur)
    			{
    				*ppFirst = cur->Next;
    				free(cur);
    				cur = NULL;
    			}
    			else//删除中间节点
    			{
    				prev->Next = cur->Next;
    				free(cur);
    				cur = NULL;
    			}
    			break;
    		}
    		prev = cur;
    		cur = cur->Next;
    	}
    }
    

    按值删除,删除所有的

    // 按值删除,删除所有的 
    void SListRemoveAll(SListNode **ppFirst, DataType data)
    {
    	SListNode *cur = NULL;
    	SListNode *prev = NULL;
    	assert(ppFirst != NULL);
    	if (*ppFirst == NULL)
    		return;
    	cur = *ppFirst;
    	while (cur)
    	{
    		if (cur->data == data)
    		{
    			//删除
    			//1.删除的是第一个节点
    			if (*ppFirst == cur)
    			{
    				*ppFirst = cur->Next;
    				free(cur);
    				cur = *ppFirst;
    			}
    			else//删除中间节点
    			{
    				prev->Next = cur->Next;
    				free(cur);
    				cur = prev;
    			}
    		}
    		prev = cur;
    		cur = cur->Next;
    	}
    }
    
    

    销毁 ,需要销毁每一个节点

    // 销毁 ,需要销毁每一个节点
    void SListDestroy(SListNode **ppFirst)
    {
    	SListNode*cur = NULL;
    	SListNode*del = NULL;
    	assert(ppFirst);
    	cur = *ppFirst;
    	while (cur)
    	{
    		del = cur;
    		cur = cur->Next;
    		free(del);
    		del = NULL;
    	}
    	*ppFirst = NULL;
    }
    

    按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL

    // 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL 
    SListNode *  SListFind(SListNode *pFirst, DataType data)
    {
    	for (SListNode *cur = pFirst; cur != NULL; cur = cur->Next)
    	{
    		if (cur->data == data)
    		{
    			return cur;
    		}
    	}
    	return NULL;
    }
    

    如有不足之处,欢迎指正!!

    展开全文
  • 单链表(完整 含main方法)

    千次阅读 多人点赞 2019-09-08 10:46:36
    链表: 通过一组任意的存储单元来存储线性表中的数据元素,由一个个结点构成。 链表之所以让初学者难以理解,是因为要回溯到上一个结点,并利用这个结点,很多人的思维一直都是往下面追溯,所以才会觉得难以理解,...

    链表:

    通过一组任意的存储单元来存储线性表中的数据元素,由一个个结点构成。

    链表之所以让初学者难以理解,是因为要回溯到上一个结点,并利用这个结点,很多人的思维一直都是往下面追溯,所以才会觉得难以理解,多动手画画图会容易理解许多。

    链表示意图:

     

     

    结点:

    结点类型如下:

    typedef struct lnode{

    datatype data; //数据域

    struct lnode *next; //指针域

    }LNode,*LinkedList;

    定义头指针变量:LinkedList L;

     

    结点示意图:

    必须将第一个结点的地址放到一个指针变量如L中,最后一个结点没有后继,其指针域必需置空,表明此表到此结束,这样就介意从第一个结点的地址开始“顺藤摸瓜”,找到每个结点。

     

     

    头结点:

    为了方便满足插入和删除基本操作,我们在链表的头部加入一个“头结点”,如果没有头结点,第一个结点的插入和删除操作跟其他结点不同,需要单独分析,为了省去这个麻烦,因此我们定义了一个头结点,头结点的类型与数据结点一致,标识链表的头指针变量L中存放该结点的地址,这样即使是空表,头指针变量L也不为空了。

    头结点的加入使得“第一个结点”的问题不存在了,也使得处理“空表”和“非空表”的操作变的一致。

    头结点的加入纯粹是为了使运算方便,它的数据域即data是没有定义的,指针域中存放的是第一个数 据结点的地址,空表时,指针域为NULL

    注:表头插入结点不需要头结点,会增加繁琐的操作,表尾插入结点增添头结点会很省事

     

     

    基本运算:

    一、建立单链表

    (1)在链表的头部插入结点

    插入的过程图:(25,45,18,76,29)链表的建立过程

    因为实在链表的头部插入,读入数据的顺序和线性中的逻辑顺序是相反的

    插入的代码:

    ​​​​//在表头插入结点 
    LinkList Create_LinkList1(){
    	L = NULL;						//定义L为空链表
    	int x;									//设数据元素为int类型
    	LNode *s;
    	scanf("%d",&x);
    	while(x!=-1){
    		s = (LNode*)malloc(sizeof(LNode));	//申请内存
    		if(s==NULL){
    			printf("申请内存空间失败!");
    			break;
    		} 
    		s->data = x;					 
    		s->next = L;						//若是第一个结点,则将NULL赋给s,从第二个开始,
    											//因为是从头部插入,所以s->next指向的是上一轮定义的结点 
    		L = s;								//头指针指向最新的结点s 
    		scanf("%d",&x);
    	} 
    	return L;								//返回头指针,通过头指针可以遍历该链表 
    }

    (2)在链表的尾部插入结点

    在链表的头部插入结点建立单链表比较简单,但读入数据元素的顺序与生成的链表中元素的顺序是相反的,若希望次序一致,则用尾插入的方法。因为每次是将新结点插入到链表的尾部,所以需要加入一个新的指针r(rear的缩写),该指针r永远指向链表中的尾结点,以便能够将新结点插入到链表的尾部。

    插入结点示意图:

    算法思路:

     初始状态:头指针 L=NULL,尾指针r=NULL。按线性表中元素的顺序依次读入数据元素,非结束标志时,申请结点,将新结点插入到r所指结点的后面,然后r指向新结点。(这里为了方便,该单链表是带有头结点的)

    代码:

     

    //在表尾插入结点
    LinkList Create_LinkList2(){
    	L = NULL;
    	LNode *s;	//定义结点 
    	LNode *r;	//定义尾指针,永远指向最后一个结点 
    	int x;
    	s = (LNode*)malloc(sizeof(LNode));	//定义头结点,申请内存
    	if(s==NULL){
    		printf("申请内存空间失败!");
    	}
    	s->next = NULL;
    	L = s;	//头指针指向头结点 
    	r = s; 	//尾指针指向头结点		注:此时链表里面没有数据结点
    	scanf("%d",&x);
    	while(x!=-1){
    		s = (LNode*)malloc(sizeof(LNode));
    		if(s==NULL){
    			printf("申请内存空间失败!");
    			break;
    		}	
    		s->data = x;
    		s->next = NULL;
    		r->next = s;	//将尾结点的next指向最新的结点 
    		r = s;			//尾指针指向最新的结点 
    		scanf("%d",&x);
    	}
    	return L; 
    }

    二、求表长

    算法思路:

    设一个移动指针p和计数器j。初始化后,p所指节点后面若还有结点,p向后移动,计数器自增即++

    //获取链表长度(带头结点)
    int Length_LinkList1(LinkList L){
    	LNode *p = L;
    	int j=0;
    	while(p->next){
    		p = p->next;
    		j++;
    	}
    	return j; 
    }
    //获取链表长度(不带头结点)
    int Length_LinkList2(LinkList L){
    	LNode *p = L;			//非空表下指向的就是第一个结点 
    	int j=0;
    	while(p){
    		j++;
    		p = p->next;
    	}
    	return j; 
    }

     时间复杂度均为O(n)

    三、查找操作

    (1)按序号操作

    算法思路:(均为带头结点的情况)

    从链表的而第一个元素结点起,判断当前结点是否是第i个,若是,则返回该结点的指针,否则,继续后一个,表结束为止。没有第i个结点时返回空。

    //按序号查找单链表中的第i个元素结点,找到返回指针,否则返回空 (带头结点) 
    LNode *Get_LinkList(LinkList L,int i){
    	LNode *p = L;
    	int j=0;
    	while(j<i&&p->next!=NULL){
    		p = p->next;
    		j++;
    	}
    	if(j==i)
    		return p;
    	else
    		return NULL;
    } 

    (2)按值操作

    算法思路:(均为带头结点的情况)

    从链表的而第一个元素结点起,判断当前结点值是否等于x,若是,则返回该结点的指针,否则,继续后一个,直到表结束为止。找不到时返回空。

    // 按值查找(带头结点)
     LNode *Locate_LinkList(LinkList L,int x){
    	LNode *p = L->next;
    	while(p!=NULL&&p->data!=x){
    		p = p->next;
    	}
    	return p;
    } 

    时间复杂度均为O(n)

     

    插入和删除操作都比较容易理解,代码中有注释,这里就不多说了

    四、插入操作

    //插入(前插结点)(带头结点)(失败返回0,成功返回1) 
    int Insert_LinkList(LinkList L,int i,int x){
    	LNode *p,*s;
    	p = Get_LinkList(L,i-1);	//获取第i-1个结点
    	if(p==NULL){
    		printf("参数i错误!\n");
    		return 0; 
    	}
    	else{
    		s = (LNode*)malloc(sizeof(LNode));	//申请、填装结点 
    		if(s==NULL){
    			printf("申请内存空间失败!");
    			return 0;
    		}
    		s->data = x;
    		s->next = p->next;
    		p->next = s;
    		return 1; 		
    	} 
    }

    五、删除操作

    //删除结点
    int Delete_LinkList(LinkList L,int i){
    	LinkList p,s;
    	p = Get_LinkList(L,i-1);	//获取第i-1个节点
    	if(p==NULL){
    		printf("第i-1个结点不存在\n");
    		return -1; 
    	}else if(p->next==NULL){
    		printf("第i个结点不存在");
    		return 0;	
    	}else{
    		s = p->next;
    		p->next = s->next;
    		free(s);	//释放*s; 
    		return 1; 
    	} 
    }

    六、遍历链表

    void Find(LinkList L){
    	LNode *p = L->next;
    	int i=0;
    	while(p){
    		i++;
    		printf("---->|Node%d->data:%d|\n",i,p->data);
    		p = p->next;
    	} 
    } 

    附完整的单链表代码:

    #include <stdio.h>
    #include <malloc.h>
    typedef int Elemtype;	//Elemtype定义为int型 
    typedef struct lnode{	//结点 
    	Elemtype data;		//数据域 
    	struct lnode *next;	//指针域 
    }LNode,*LinkList;		//LNode是结点类型,LinkList是指向LNode类型结点的指针类型 
    LinkList L;			//定义头指针变量 
     
    //在表头插入结点 
    LinkList Create_LinkList1(){
    	L = NULL;						//定义L为空链表
    	int x;									//设数据元素为int类型
    	LNode *s;
    	scanf("%d",&x);
    	while(x!=-1){
    		s = (LNode*)malloc(sizeof(LNode));	//申请内存
    		if(s==NULL){
    			printf("申请内存空间失败!");
    			break;
    		} 
    		s->data = x;					 
    		s->next = L;						//若是第一个结点,则将NULL赋给s,从第二个开始,
    											//因为是从头部插入,所以s->next指向的是上一轮定义的结点 
    		L = s;								//头指针指向最新的结点s 
    		scanf("%d",&x);
    	} 
    	return L;								//返回头指针,通过头指针可以遍历该链表 
    } 
     
    //在表尾插入结点
    LinkList Create_LinkList2(){
    	L = NULL;
    	LNode *s;	//定义结点 
    	LNode *r;	//定义尾指针,永远指向最后一个结点 
    	int x;
    	s = (LNode*)malloc(sizeof(LNode));	//定义头结点,申请内存
    	if(s==NULL){
    		printf("申请内存空间失败!");
    	}
    	s->next = NULL;
    	L = s;	//头指针指向头结点 
    	r = s; 	//尾指针指向头结点		注:此时链表里面没有数据结点
    	scanf("%d",&x);
    	while(x!=-1){
    		s = (LNode*)malloc(sizeof(LNode));
    		if(s==NULL){
    			printf("申请内存空间失败!");
    			break;
    		}	
    		s->data = x;
    		s->next = NULL;
    		r->next = s;	//将尾结点的next指向最新的结点 
    		r = s;			//尾指针指向最新的结点 
    		scanf("%d",&x);
    	}
    	return L; 
    }
     
    //获取链表长度(带头结点)
    int Length_LinkList1(LinkList L){
    	LNode *p = L;
    	int j=0;
    	while(p->next){
    		p = p->next;
    		j++;
    	}
    	return j; 
    }
     
    //获取链表长度(不带头结点)
    int Length_LinkList2(LinkList L){
    	LNode *p = L;			//非空表下指向的就是第一个结点 
    	int j=0;
    	while(p){
    		j++;
    		p = p->next;
    	}
    	return j; 
    }
     
    //按序号查找单链表中的第i个元素结点,找到返回指针,否则返回空 (带头结点) 
    LNode *Get_LinkList(LinkList L,int i){
    	LNode *p = L;
    	int j=0;
    	while(j<i&&p->next!=NULL){
    		p = p->next;
    		j++;
    	}
    	if(j==i)
    		return p;
    	else
    		return NULL;
    } 
     
    // 按值查找(带头结点)
     LNode *Locate_LinkList(LinkList L,int x){
    	LNode *p = L->next;
    	while(p!=NULL&&p->data!=x){
    		p = p->next;
    	}
    	return p;
    } 
     
    //插入(前插结点)(带头结点)(失败返回0,成功返回1) 
    int Insert_LinkList(LinkList L,int i,int x){
    	LNode *p,*s;
    	p = Get_LinkList(L,i-1);	//获取第i-1个结点
    	if(p==NULL){
    		printf("参数i错误!\n");
    		return 0; 
    	}
    	else{
    		s = (LNode*)malloc(sizeof(LNode));	//申请、填装结点 
    		if(s==NULL){
    			printf("申请内存空间失败!");
    			return 0;
    		}
    		s->data = x;
    		s->next = p->next;
    		p->next = s;
    		return 1; 		
    	} 
     
    }
     
    //删除结点
    int Delete_LinkList(LinkList L,int i){
    	LinkList p,s;
    	p = Get_LinkList(L,i-1);	//获取第i-1个节点
    	if(p==NULL){
    		printf("第i-1个结点不存在\n");
    		return -1; 
    	}else if(p->next==NULL){
    		printf("第i个结点不存在");
    		return 0;	
    	}else{
    		s = p->next;
    		p->next = s->next;
    		free(s);	//释放*s; 
    		return 1; 
    	} 
    }
     
    //遍历链表
    void Find(LinkList L){
    	LNode *p = L->next;
    	int i=0;
    	while(p){
    		i++;
    		printf("---->|Node%d->data:%d|\n",i,p->data);
    		p = p->next;
    	} 
    } 
     
    void list(){
    	printf("This is a Singly Linked List.\n------------------------------------------\nPlease press the button:\n");
    	printf("Button 1 ---> Create_LinkList()\n");				//创建单链表 (带头结点、表尾插入)
    	printf("Button 2 ---> Length_LinkList(L)\n");				//获取链表长度
    	printf("Button 3 ---> Get_LinkList(L,i)\n");				//按序号查找 
    	printf("Button 4 ---> Locate_LinkList(L,x)\n");				//按值查找 
    	printf("Button 5 ---> Insert_LinkList(L,i,number)\n");		//插入结点 
    	printf("Button 6 ---> Delete_LinkList(L,i)\n");				//删除结点 
    	printf("Button 7 ---> Find(L)\n");							//遍历链表 
    	printf("Button 8 ---> Exit the program\n-----------------------------------\n");					//退出程序 
    }
     
     
    int main(){
    	list();
    	while(true){
    	printf("Choose Button: ");	
    		int n;
    		int flag =1;
    		int length,i,number,item;//item用于Insert插入和Detele删除的返回数据 
    		LNode *p;
    		scanf("%d",&n);
    		switch(n){
    			case 1:
    				printf("If you enter '-1',the list is created\n");			//若输入-1,则表示链表元素创建完成 
    				L = Create_LinkList2();
    				printf("--------------------------------------------------------\n");
    			break;
    				
    			case 2:
    				if(L==NULL)
    				{	
    					printf("Sorry!Wrong!\n-------------------------------------------------\n");
    					break;
    				}
    				length = Length_LinkList1(L);
    				printf("The Singly Link List length is: %d\n-------------------------------------\n",length);		//单链表的长度为: 
    			break;	
     
    			case 3:
    				printf("Please enter you want to find serial number-->i:  ");//请输入你想查找的序号 
    				scanf("%d",&i);
    				if(L==NULL)
    				{	
    					printf("Sorry!Wrong!\n-------------------------------------------------\n");
    					break;
    				}
    				p =Get_LinkList(L,i);
    				if(p==NULL){
    					printf("Sorry!Wrong!\n----------------------------------------------\n");			//第i个位置为NULL,错误 
    				}else{
    					printf("Successsful!The Node data is:%d\n--------------------------------------\n",p->data);//不为NULL,查找成功,输出该结点数据域 
    				} 	
    			break;
    				
    			case 4:
    				printf("Please enter you want to find number:  ");
    				scanf("%d",&number);
    				if(L==NULL)
    				{	
    					printf("Sorry!Wrong!\n-------------------------------------------------\n");
    					break;
    				}
    				p = Locate_LinkList(L,number);
    				if(p==NULL)
    					printf("Sorry!Wrong!\n-------------------------------------------------\n");			//第i个位置为NULL,错误 
    				else
    					printf("Successsful!The Node data is:%d\n-------------------------------------------\n",p->data);//不为NULL,查找成功,输出该结点数据域  
    			break;
    				
    			case 5:							//插入结点 
    				printf("Please enter i and number:  ");
    				scanf("%d%d",&i,&number);
    				item = Insert_LinkList(L,i,number);
    				if(item==0)
    					printf("Insert failed-----------------------------------------------------\n");
    				else
    					printf("Insert successful--------------------------------------------------------\n");
    			break;
    				
    			case 6:									//删除结点 
    				printf("Please enter i:  ");
    				scanf("%d",&i);
    				item = Delete_LinkList(L,i);
    				if(item==0 || item==-1)
    					printf("Delete failed----------------------------------------------------------\n");
    				else
    					printf("Delete successful-------------------------------------------------------------\n");
    			break;
    							
    			case 7:
    				printf("Traverse Singly Linked List:\n");		//遍历该单链表 
    				if(L==NULL)
    				{	
    					printf("Sorry!Wrong!\n-------------------------------------------------\n");
    					break;
    				}
    				Find(L); 
    				printf("-------------------------------------------------------------------------\n");
    			break;
    			
    			case 8:
    				printf("Exit the program successful!\n");
    				flag = -1;
    			break;
    						 
    			default:
    				printf("Sorry!You can't do that!\n");
    				flag = -1;
    			break;	
    		}
    		if(flag==-1)
    		break;
    	}
     
    }

    单链表的缺点(最主要):

    不具有随机访问的特点,只能从头指针开始一个个顺序操作进行

    展开全文
  • 【C语言】链表及单链表基本操作

    万次阅读 多人点赞 2019-04-29 15:20:45
    1、什么是链表?链表的分类? 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 数据结构中: 2、链表的分类 共有8种链表结构 ......
  • 单链表

    2020-04-22 21:12:56
    一、单链表简述 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素+ 指针,元素就是存储数据的存储单元,指针就是连接每个...
  • 单链表的实现

    万次阅读 多人点赞 2019-06-21 11:30:56
    关于单链表的一些操作,今天重新梳理了一下 话不多说,先上代码 #include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR 0 typedef int ElemType,Status; typedef struct LNode{ ...
  • 1,单链表,双链表的定义: 设计链式存储结构时,每个逻辑节点存储单独存储。 2,单链表的基本结构: 头节点在前,首节点在后。 3,顺序表与链表间存储密度的差异: 顺序表的存储密度为1,而链表的存储...
  • 单链表常见操作图文详解

    万次阅读 多人点赞 2018-04-15 20:58:27
    单链表的最大特点是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查等功能。 单链表分为两种:有头链表和无头链表。 无头单链表,也就是phead一只是一个指针,指向链表的第一...
  • 试写一算法,对单链表实现就地逆置。 实现下列函数: void Inverse(LinkList &L);  /* 对带头结点的单链表L实现就地逆置 */ 单链表类型定义如下: typedef struct LNode{  ElemType data;  struct...
  • 已知一个带有头结点的单链表,设计算法将该单链表复制一个拷贝,急急急
  • 带头结点的单链表head为空的判定条件( ) 正确答案: B 你的答案: C (错误) head==NULL head->next==NULL head->next==head head!=NULL 添加笔记 收藏 纠错 ...
  • 借助栈实现单链表上的逆置运算。

    千次阅读 2018-04-22 22:03:55
    本小白刚学数据结构,没想到到栈这里就难住了,不知道怎么跟链表结合,不知道有没有大神指点一下 借助栈实现单链表上的逆置运算。用c++怎么实现...
  • 单链表拆分为两个特定的单链表

    千次阅读 2016-09-22 21:16:50
    将一个给定的单链表拆分为两个特定的单链表
  • 用C语言计算一个单链表的长度,单链表的定义如下:要求使用递归,不得出现循环。
  • C++创建单链表

    万次阅读 2016-03-15 22:04:46
    下面是C++创建单链表的代码,记录一下省的自己以后忘了(有些头文件没用,我没挑一块粘上来了) #include using namespace std; /* 创建一个单链表 */ struct ListNode{ int m_key; ListNode
  • 单链表为空的判定条件

    千次阅读 2019-06-03 16:05:43
    带头结点的单链表head为空的判定条件是()。 A.head==NULL B.head->next==NULL C.head->next==head D.head!=NULL 正确答案:B 解析:若单链表带头结点,那么判定它为空的条件是head->next==NULL;若...
  • 销毁单链表

    千次阅读 2017-12-17 10:22:41
    void DestroyList(LinkList *L) { LinkList q,p=*L;//让p指向头结点 while(p!=0){//当头结点的指针域不为0,即不是链尾时 q=p->next;//让q指向头结点的后续结点 delete p;//删除p ...//让p和q都指向后续结点 } ...
  • 删除单链表中重复元素(或结点)

    千次阅读 2018-10-03 17:13:51
    剔除单链表重复元素(或结点) //剔除单链表重复元素(或结点) void pur_LinkList(LinkList L){ Lnode *p,*s,*q; p=L-&amp;gt;next; if(!p) return; while(p-&amp;gt;next) { q=p; while...
  • /*---编写打印出一个单链表的所有元素的程序---*/ #include #include struct Node{ int val; struct Node *next; }; Node *findEnd(Node *list){ while(list->next) list = list->next; return list; } v
1 2 3 4 5 ... 20
收藏数 106,668
精华内容 42,667
关键字:

单链表