• 单链表之C++实现


            在实现单链表时要注意对单链表的逻辑存储、物理存储有清晰的概念。

    如上图链表已经完成,其逻辑结构如上。当需要对其进行操作,比如插入、删除,通常需要引

    指针,如上的ptr1、ptr2。在编程时一定要注意通过ptr1、ptr2对链表结构的操作是正确的。

    不仅仅是你觉得正确的。

    下面给大家看下我的单链表的实现,错误之处还请指正。

    1、VC6实现,包括三个文件:sll.h、sll.c、main.c

    2、sll.h单链表类、结点类的说明

    #ifndef _SLL_H_
    #define _SLL_H_
    
    //加以下两句是为了使链表中包含的数据类型可以更灵活
    #define dataType int
    #define endOfData 0
    
    //单链表的节点
    class node
    {
    public:
    	dataType data;
    	node *next;
    };
    
    //单链表,其中保存的元素为整数
    class sll
    {
    public:
    	sll();				//构造函数
    	~sll();				//析构函数
    	void create();			//建立一个链表
    	int getLength();			//获取链表长度
    	void reverse();			//链表倒置
    	bool insert(int pos,dataType num);  //插入某一位置的某一值.插入成功返回true;否则返回false.位置从0开始向上累加
    	void del(dataType num);		//删除某一所有值
    	node* getHead();			//获取链表头
    	void print();                       //打印所有元素
    	int find(dataType num);             //在链表中寻找num.若找到返回首次找到的下标,若找不到则返回-1
    	dataType getNum(int pos);           //根据pos找到对应结点的data域的值,若找不到则返回endOfData
    
    private:
    	node *head;			//链表头指针
    };
    
    #endif

    3、sll.c单链表类成员函数的实现

    #include <iostream>
    #include "sll.h"
    using namespace std;
    
    sll::sll()       //构造函数
    {
    	head = NULL;
    }
    
    sll::~sll()      //析构函数
    {
    	node *ptrNode = head;
    	node *ptrNodeTmp = NULL;
    
    	while(ptrNode != NULL)
    	{
    		ptrNodeTmp = ptrNode->next;
    		delete ptrNode;
    		ptrNode = ptrNodeTmp;
    	}
    }
    
    void sll::create()
    {
    	node *ptrNode = new node;
    	ptrNode->data = endOfData;
    	head = ptrNode;              //保存头结点指针
    
    	bool flag = true;            //flag=true继续建单链表,flag=false链表建立完成
    	bool flagNumOne = true;      //flagNumOne表示是链表的第一个元素
    	dataType data = endOfData;   //dataType和endOfData在sll.h中定义
    
    	while(flag)
    	{
    		cout<<"输入节点数据: ";  //一个一个的输入结点
    		cin>>data;
    
    		if(data != endOfData)    
    		{                        //没有输入建链表结束标志endOfData,则继续建链表
    			if(!flagNumOne)
    			{
    				node *tmpPtr = new node;
    
    				ptrNode->next = tmpPtr;
    				ptrNode = tmpPtr;
    			}
    
    			ptrNode->data = data;
    
    			flagNumOne = false;
    		}
    		else
    		{                        //输入结束标志endOfData,则结束建链表
    			flag = false;
    			ptrNode->next = NULL;
    		}
    	}
    
    	if(head->data == endOfData)       //链表为空的情况
    	{
    		head = NULL;
    		delete ptrNode;          //如果链表中没有元素,则要释放程序申请的唯一结点
    	}
    }
    
    int sll::getLength()
    {
    	int num = 0;
    	node *ptrNode = head;
    
    	while(ptrNode != NULL)
    	{
    		num++;                     //未到链表结尾则继续累加
    		ptrNode = ptrNode->next;   //链表延展
    	}
    
    	return num;
    }
    
    void sll::del(dataType num)
    {
    	//ptrNodeMain和ptrNodeAssit在起始时是指向同一结点的,以后都是指向一前一后的两个点,ptrNodeAhead在前(更接近链表结束)
    	node *ptrNodeAhead = head;
    	node *ptrNodeFellow = ptrNodeAhead;
    
    	while(ptrNodeAhead != NULL)       //链表要从头找到尾,删除链表中所有等于num的结点
    	{
    		while(ptrNodeAhead->data != num && ptrNodeAhead->next != NULL)  //未找到num结点,也未到链表结尾,指针向下扩展
    		{
    			ptrNodeFellow = ptrNodeAhead;
    			ptrNodeAhead = ptrNodeAhead->next;
    		}
    
    		if(ptrNodeAhead->data == num)   //找到num结点
    		{
    			if(ptrNodeAhead == head)    //如果num节点是头结点
    			{
    				head = ptrNodeAhead->next;
    				delete ptrNodeAhead;
    				ptrNodeAhead = head;
    				ptrNodeFellow = ptrNodeAhead;
    			}
    			else                       //如果num节点不是头结点
    			{
    				ptrNodeFellow->next = ptrNodeAhead->next;
    				delete ptrNodeAhead;
    				ptrNodeAhead = ptrNodeFellow->next;
    			}
    		}
    		else                           //链表搜索结束也未找到num结点
    		{
    			ptrNodeAhead = NULL;
    		}
    	}
    }
    
    bool sll::insert(int pos,dataType num)
    {
    	if(pos < 0 || pos >= getLength())  //判断插入结点的正确位置是(0 ~ getLength()-1)
    	{
    		return false;
    	}
    
    	node *ptrNodeAhead = head;
    	node *ptrNodeFollow = NULL;
    	int tmpNum = 0;
    	while(1)  //获取插入位置的指针,ptrNodeAhead指向待插入的位置,ptrNodeFollow指向带插入位置的下一结点
    	{	
    		if(tmpNum++ == pos)
    		{
    			break;
    		}
    
    		ptrNodeFollow = ptrNodeAhead;
    		ptrNodeAhead = ptrNodeAhead->next;
    	}
    
    	//以下两句将待插入结点的数据准备好
    	node *ptrTmpNode = new node;
    	ptrTmpNode->data = num;
    
    	if(ptrNodeAhead == head)      //如果是插入头结点
    	{
    		ptrTmpNode->next = head;
    		head = ptrTmpNode;
    	}
    /*
    	else if(ptrNodeAhead->next == NULL)
    	{
    		ptrNodeAhead->next == ptrTmpNode;
    		ptrTmpNode->next = NULL;
    	}
    */
    	else                         //插入中间节点,此种方法永远也不能插入尾结点,插入是前向的
    	{
    		ptrNodeFollow->next = ptrTmpNode;
    		ptrTmpNode->next = ptrNodeAhead;
    	}
    
    	return true;
    }
    
    node* sll::getHead()
    {
    	return head;              //返回链表头结点指针
    }
    
    void sll::reverse()
    {
    	node *ptrNodeAhead = head;
    	node *ptrNodeFllow = NULL;
    	node *ptrTmp = NULL;
    
    	while(ptrNodeAhead != NULL)
    	{
    		ptrTmp = ptrNodeAhead->next; 
    		ptrNodeAhead->next = ptrNodeFllow;
    		ptrNodeFllow = ptrNodeAhead;
    		ptrNodeAhead = ptrTmp;
    	}
    
    	head = ptrNodeFllow;
    }
    
    void sll::print()
    {
    	node *ptrNode = head;
    
    	while(ptrNode != NULL)
    	{
    		cout<<ptrNode->data<<" ";
    
    		ptrNode = ptrNode->next;
    	}
    	cout<<endl;
    }
    
    int sll::find(dataType num)
    {
    	node *ptrNode = head;
    	int index = 0;
    
    	while(ptrNode != NULL)
    	{
    		if(ptrNode->data == num)
    		{
    			return index;   //返回第一个num结点的下标
    		}
    
    		++index;
    		ptrNode = ptrNode->next; //链表向下延展
    	}
    
    	return -1;                        //未找到num结点返回-1
    }
    
    dataType sll::getNum(int pos)
    {
    	if(pos < 0 || pos >= getLength())  //判断pos的正确位置是(0 ~ getLength()-1)
    	{
    		return endOfData;
    	}
    
    	int index = 0;
    	node *ptrNode = head;
    
    	while(1)
    	{
    		if(index++ == pos)
    		{
    			return ptrNode->data;
    		}
    
    		ptrNode = ptrNode->next;
    	}
    }


    4、main.c

    #include <iostream>
    #include "sll.h"
    using namespace std;
    
    int main()
    {
    	sll exp;
    
    	exp.create();
    	
    	cout<<"The len of sll: "<<exp.getLength()<<endl;
    	exp.print();
    
    	exp.del(2);
    	exp.print();
    
    	exp.insert(2,999);
    	exp.print();
    
    	exp.reverse();
    	exp.print();
    
    	cout<<"2的位置在: "<<exp.find(2)<<endl;
    
    	cout<<exp.getNum(3)<<endl;
    
    	return 0;
    }

    5、测试结果

  • 相关阅读:
    日期控件选择条件控制只能选择当前日期之前或当前日期之后
    记录一次ajax 429请求laravel api的错误
    如何配置Linux系统的IP地址?
    laravel 定时任务通过队列发送邮件
    ioutil.ReadFile 读取文件内容时为什么读取不到文件呢?open var2.go: no such file or directory
    swoole异步io操作
    PHP获取本周所有日期或者最近七天所有日期
    面试又给我问到MySQL索引,最全的一次整理
    Google资深工程师深度讲解Go语言基础语法(二)
    ps命令详解
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3281535.html
Copyright © 2020-2023  润新知