数据结构学习笔记(一) 链表以及基本操作

写完贴在这里 做


#include <iostream>
using namespace std;

class List
{
	//内部类型成员
	typedef int T;
	//内部类型成员  受访问权限影响  
	struct Node
	{
		T data;
		Node* next;
		//一旦你写了构造函数 就不能再以前的方法初始化
		// d = T() 零初始化 基本数据类型表示0 自定义数据类型表示无参构造函数
		Node(const T& d = T() ):data(d),next(NULL) 
		{	
		}
	};
	
	Node* head; //头指针,用来保存头节点地址 。 有头节点的链表这里直接是Node对象
	int len;
public:
	List():head(NULL),len(0) { }
	~List()
	{
		clear();
	}
	
	//函数的返回值如果是List型的 一定要是指针或者引用
	//如果以值类型返回,由于head都指向同一个地方 ,在临时变量析构时会释放链表中所有的空间  
	
	//个数 有n个数则返回n
	int size() const
	{
		return len;
	}
	
	
	//前插
	void push_front(const T& d)
	{
		/*
		Node* p = new Node(d); //这里不可以用局部变量 因为局部变量会销毁
		p->next = head;
		head = p;
		*/
		insert(d,0);
	}
	//后插
	void push_back(const T&d)
	{
		insert(d,size()); //少用一次变量  出错几率就少一次 len 与 size()的区别
	}
	
	//找链表中指向指定位置的指针
	// 返回引用类型  保证返回的是指针本身
	// 如果不是引用 那就是值传递了。
	//pos 从0~n 有n+1个位置  0~n都可以插值  位置0~n-1是用来删除和修改的 
	 //因为我想在将来改变返回的这个指针的指向,所以写引用。
	 //若是值传递,我在调用函数后只能得到一个相同指向的指针,这样只能修改指向的对象的值
	 //,但却无法修改返回的这个指针的指向。
	Node*& getptr(int pos) 
	{
		if(pos == 0) return head;
		
		Node *p = head;
		//1 return p->next
		//2 p=p->next ; return p->next
		for(int i =1; i < pos; i++)
		{
			p = p->next;
		}
		return p->next;
	}
	
	//在任意位置插入
	//1在链表里找到指向这个位置的指针
	//2 新节点指和找到的指针指向同一个地方
	//3 指针指向新节点 ++len
	void insert(const T& d,int pos) //n个节点 有n+1个插入 pos  0~n
	{
		if(pos <0 || pos > size() ) pos = 0;
		Node* &p = getptr(pos); //继续引用 
		Node *pn  = new Node(d);
		pn -> next = p;
		p = pn;
		len ++;
	}
	
	//遍历
	void travel() const
	{
		Node *p = head;
		while(p != NULL)
		{
			cout << p->data  << ' ';
			p = p->next;
			
		}
		cout << endl;
	}
	
	//按位置删除
	//插入可以有n+1个位置 删除有n个位置 0~n-1
	//1找到指向这个节点的指针
	//2 保存指针 为temp  指针指向这个节点的下一个节点 
	//3 释放temp的空间  --len
	void erase(int pos)
	{
		if(pos < 0 || pos > size() -1) //无效位置
		{
			return;
		}
		
		
		Node* &p = getptr(pos);
		Node *temp = p;
		p = p->next;
		delete temp;
		--len;
		
	}
	
	//按数值来得到指向节点的指针
	int  find(T d)
	{
		Node *p = head;
		int pos = 0;
		while( p != NULL)
		{
			if( (p->data) == d ) return pos;
			p = p->next;
			pos ++;
		}
		return -1;
	}
	
	
	//按数值来删除节点 删除链表中所有的这个值
	void remove(T d)
	{
		int pos;
		while( (pos=find(d)) != -1 )
		{
			erase(pos);
		}
	}
	
	//修改节点
	void set(int pos ,T d)
	{
		if(pos < 0 || pos > size()-1) return;
		getptr(pos) -> data = d;
	}
	
	bool empty() const
	{
		return head==NULL;
	}
	
	//返回头节点数据
	T front() const 
	{
		if(empty() ) throw "链表为空";
		return head->data;
	}
	
	//返回尾节点数据
	T back() const
	{
		if( empty() ) throw "链表为空";
		Node *p = head;
		while(p->next != NULL)
		{
			p = p->next;
		}
		
		return p->data;
	}
	
	//链表反转
	void reverse()
	{
		//因为前面用了指针的引用,让我出现疑惑 
		//这里为什么不用引用呢?
		//因为无论是函数形参还是返回值都存在值传递的问题,导致实际操作的
			//是一个相同指向的临时指针 。
		//而这个函数中不存在传递问题,是对指针的直接操作。
		
		Node *p = head;
		Node *p_next = NULL;
		Node *p_pre =NULL;
		
		while(p != NULL)
		{
			p_next = p->next;
			p->next = p_pre;
			p_pre = p;
			p = p_next;
		}
		head = p_pre;
	}
	
	
	//清空
	void clear()
	{
		while(head != NULL)
		{
			Node* p  = head->next;
			delete head;
			head = p;
		}
		head = NULL;
		len = 0;
	}
};

int main()
{
	List l;
	cout << sizeof(l) << endl; // 大小 8 
	
	l.push_front(1);//头插
	l.push_front(10);
	l.push_front(100);
	l.travel(); //100 10 1 
	
	l.insert(1000,0); 
	l.travel();//1000 100 10 1
	l.push_back(10000); //1000 100 10 1 10000 
	l.travel();
	
	l.insert(70,-1); // pos不正确 纠正为0
	l.travel();//70 1000 100 10 1 10000
	l.insert(7000,200); //pos不正确 纠正为0
	l.travel();//7000 70 1000 100 10 1 10000 
	
	l.erase(100); //无效的位置  直接返回
	l.travel();//7000 70 1000 100 10 1 10000 
	l.erase(5);//删除5号位置 即第六个位置
	l.travel(); //7000 70 1000 100 10 10000
	
	
	//插入重复的值
	l.insert(999,2);
	l.insert(999,5);
	l.insert(999,6);
	l.travel();//7000 70 999 1000 100 999 999 10 10000 
	l.remove(999); //按值删除
	l.travel();//7000 70 1000 100 10 10000
	
	//修改
	l.set( l.find(10) , 9 ); //将10改成9
	l.travel();//7000 70 1000 100 9 10000
	l.set(0,8);//将第0个改成8
	l.travel();//8 70 1000 100 9 10000
	
	
	cout  << boolalpha  << l.empty() << endl; //false	
	cout << l.front() << ' ' << l.back() << endl;//8 10000
	
	//cout << l.getptr(l.size() -1)->data << endl;
	cout << "reverse : ";
	l.reverse();
	l.travel();
	
	
	// l.clear();清空
		
	//清空
	while( !l.empty() )
	{
		l.erase(0);
	}
	cout << "size :"  << l.size() << endl;

	
	
	return 0;
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值