zoukankan      html  css  js  c++  java
  • 单链表之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、测试结果

  • 相关阅读:
    升级windows 11小工具
    windows 10更新升级方法
    您需要了解的有关 Oracle 数据库修补的所有信息
    Step by Step Apply Rolling PSU Patch In Oracle Database 12c RAC Environment
    Upgrade Oracle Database Manually from 12.2.0.1 to 19c
    如何应用版本更新 12.2.0.1.210420(补丁 32507738 – 2021 年 4 月 RU)
    xtrabackup 安装、备份和恢复
    Centos_Lvm expand capacity without restarting CentOS
    Centos_Lvm_Create pv vg lv and mount
    通过全备+relaylog同步恢复被drop的库或表
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3281535.html
Copyright © 2011-2022 走看看