单向链表的算法实现

#include <iostream>
#include <Windows.h>

using namespace std;
//定义一个链表
typedef struct _Linknode {

	int data;    //节点的数据域
	struct _Linknode* next;  //节点的指针域

} Linklist, Linknode;//1. 表示首节点 2.表示节点


//初始化链表

bool Initlist(Linklist* &list) {
	//这里是意思是创建一个首节点  
	//
	list = new Linknode;

	if (!list) {
		return false;   //如果分配内存失败结束程序返回假
	}
	list->next = NULL;
	return true;
}

//前插法
bool Listinsert(Linklist* &list, Linknode* &node) {

	if (!list || !node) {
		cout << "list或者node为空,程序结束"; 
		return false;
	}
	//前插法 把首节点的next 赋值给 新节点的next(如果只有一个首节点那么新节点的next指向为空)
	//然后把首节点next指向 新节点本身  以此类推创建多个节点
	node->next = list->next;
	list->next = node;
	return true;


}

//后插法插入链表
bool listInsert_back(Linklist* &list, Linknode* &node) {
	Linknode* last = NULL;
	
	if (!list || !node) {
		cout << "返回false,程序结束";
		system("pause");
		return false;
	}
	last = list->next;

	while (last->next) {
		//如果last的next不为空的话 一直赋值给下一个节点
		//如果last的next指针为空的话 说明已经找到最后一个节点了
		//那么就循环条件不成立了
		last = last->next;
	}
	
	//找到最后一个节点后  要在最后一个节点后插入节点
	//那么就是把 last(上次循环找到的最后一个节点) 指向要插入的新节点
	//然后把新插入节点的next指向空. 以此类推
	last->next = node;
	node->next = NULL;
	return true;
}


// 由用户任意指定位置插入节点
//需要传递三个参数1. 首节点  2.要插入的节点的位置int i 3.要插入节点的数据 int e

bool linkInsert_rand(Linklist*& list, int i, int e) {
	if (!list) {
		return false;
	}

	int j = 0;   //用于计数 找到要新插入节点的位置
	Linknode* p = NULL;  //临时指针
	Linknode* s = NULL;  //要插入的新节点的指针
	//要想实现在任意位置插入节点的话 那么就要先找到插入节点的位置
	//方法就是 先创建一个临时指针P 先指向首节点 然后while循环
	//如果节点的位置是5  那么要插入的节点位置就是5-1  
	//小学数学问题  要插入的位置是 n的话 那么他的位置就是n-1 
	
	p = list;  //从首节点开始找



	//就是要插入的节点在哪个位置 就循环多少次
	while (p && (j < i - 1)) {  //判断指针p不为空 而且 j<i-1 来控制循环次数					
		p = p->next;			
		j++;
	}
	
	//如果 i=负数 的话 那么上面while循环的j永远不会i-1  那么循环会一直进行
	// p为NULL  也就是到最后一个节点... 那么这个时候就是非法的了
	//如果用户输入的数据大于已有节点的数量 p会一直遍历到最后一个节点 导致p=NULL
	//那么就需要下面的防御性检查了...
	//合法性检查 如果p为空的话 说明插入的位置已经超过节点数量了
	//那么就是非法的 或者用户输入的插入位置小于0 

	if (!p || j > i - 1) { 
		return false;
	}
	s = new Linknode;   //前面找到为插入节点的位置以后  新节点传入数据
	s->data = e;
	s->next = p->next; //新节点的next指向 插入点位置前面节点的next(p->next)
	p->next = s;		//然后再把前面位置节点(p->next)指向新节点本身
	return true;
}

//查找链表数据 (按位置查找)

bool link_GetElem(Linklist*& list, int i, int& e) {
	int index = 0;  //用于计数
	Linklist* p = NULL;   //临时指针用来遍历链表

	if (!list || !list->next) {
		return false;  //如果list为空   那么就说明没有任何节点 
		               //或者list.next为空 说明只有一个节点 那么就没必要查找了
	}

	index = 1;
	p = list->next;

	while (p && index < i) {
		p = p->next;
		index++;
	}

	if (!p || index > i) {  //防止p为空 或者 用户输入非法的位置 把程序搞崩
		return false;
	}
	e = p->data;
	return true;
}
//查找链表数据 (按值查找)

bool link_FindElem(Linklist*& list, int e,int &index) {

	Linklist* p = NULL;
	index = 1;
	if (!list || !list->next) {
		index = 0;
		return false;
	}
	p = list->next;

	while (p && p->data != e) { //p不能为空, 遍历链表如果数据不是要查找的数据
								//那么p就移向下一个节点
		p = p->next;
		index++;
	}

	if (!p) {          //如果p为空 那么就说明遍历链表全部数据了 然后查无此值
		index = 0;		//p遍历到链表的全部数据才会为空  因为最后一个节点next是空
		return false;
	}

	return true;

}

//删除链表的节点

bool linkDelete(Linklist*& list,int i) {
	Linklist* p = NULL;   //临时指针用来遍历链表
	Linklist* q = NULL;   // 保存要被删除的节点
	int index = 0;

	p = list;
	while (p->next && index < i - 1) {
		p = p->next;
		index++;
	}
	if (!p || index > i - 1) { //p为空或者index大于i-1删除位置不合法
		return false;
	}
	q = p->next;           //临时保存要被删除的节点 以后用来delete
	p->next = q->next;     //p的next指向被删除节点的下一个节点
	delete q;

	return true;
}

//单链表的销毁
void linkDestroy(Linklist*& list) {

	Linklist* p = NULL;
	cout << "销毁链表!!" << endl;
	p = list;

	while (p) {
		list = list->next;  //list指向下一个节点
		delete p;           //删除当前节点
		p = list;
	}

}

//遍历链表数据(打印链表)
//需要传入首节点 根据首节点 找到后面的节点
void linkPrint(Linklist*& list) {
	
	Linknode* p = NULL;

	if (!list) {
		cout << "链表为空";
		return;
	}
	
	//遍历链表数据首先建立一个临时指针然后指向首节点的next
	//然后循环遍历 因为节点本身的next就是指向下一个节点的  
	//所以 通过每个节点的next 来访问下一个节点 
	//只需要把每个节点的next 赋值给 临时指针p  然后逐次打印每个节点的data
	// 那么就实现了遍历真个链表
	p = list->next;
	int i = 1;
	while (p) {   // 如果下一个节点的next为空 那么就是最后一个节点了 那么结束循环停止遍历
		cout <<"节点"<<i++<<"数据:"<< p->data << endl; //打印当前指向节点的数据
		p = p->next;    //p赋值给下一个节点的指针
	}
	
}

int main(void) {
	cout << "--------单向链表的算法实现--------" << endl;
	Linklist* list= NULL;
	Linknode* s = NULL;
	//1.初始化一个单链表
	Initlist(list);

	//2.使用前插法插入数据
	cout << "1.------使用前插法插入节点------" << endl;
	int n;
	cout << "前插法创建单链表:";
	cin >> n;
	cout << "请以此输入n个元素:";

	while (n > 0) {
		//每循环一次就创建一个linknode类型的动态内存表示创建一个节点
		//然后让用户输入data  然后再调用插入函数 把每个节点链接起来
		s = new Linknode;//创建新的节点
		cin >> s->data;
		Listinsert(list, s);
		n--;
	}
	//遍历链表 打印数据
	linkPrint(list);

	//3. 使用后插法插入节点
	cout << "2.------使用后插法插入节点---------"<<endl;


	cout << "后插法创建单链表:";
	cin >> n;
	cout << "请以此输入n个元素:";

	while (n > 0) {

		s = new Linknode;//创建新的节点
		cin >> s->data;
		listInsert_back(list, s);
		n--;
	}
	//遍历链表 打印数据
	linkPrint(list);

	//4. 任意位置插入节点'
	cout << "3.------任意位置插入节点------" << endl;
	int i, e;
	cout << "请输入插入节点的位置:";
	cin >> i;
	cout << "请输入要插入节点的data(数据):";
	cin >> e;
	if (linkInsert_rand(list, i, e)) {
		cout << "插入成功!!" << endl;
	}
	else {
		cout << "插入失败!!" << endl;
	}
	linkPrint(list);


	//5. 查找链表的数据(按位置查找值)
	
	int elems = 0;
	if (link_GetElem(list, 2, elems)) {
		cout << "获取第二个元素成功,值为:" << elems << endl;
	}
	else {
		cout << "获取失败!!" << endl;
	}

	//6. 查找链表的数据(按值查找 并返回位置)

	int index = 0;

	if (link_FindElem(list, 100, index)) {
		cout << "找到数据100存在,位置在:" << index << endl;
	}
	else {
		cout << "查无此值!!" << endl;
	}

	//7. 单链表节点的删除

	if (linkDelete(list, 2)) {
		cout << "删除成功!!" << endl;
	}
	else {
		cout << "删除第二个节点失败" << endl;
	}
	linkPrint(list);

	//8. 单链表的销毁
	linkDestroy(list);





	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值