带头节点链表的操作(链表的创建、删除、查找、逆转、打印等等)

#include<iostream>
#include<cassert>
using namespace std;

class Node
{
public:
	int data;
	Node* next;
};

typedef class Node List_Node;

/*---------------------------------------------------------
在链表的末端插入新的节点,创建链表:这里我建立的是带有头节点
的链表,头结点的数据域是null,指针域存储的是第一个节点的地址
-----------------------------------------------------------*/
List_Node *creat(int n)
{
	List_Node *head;//头指针
	List_Node *p1, *p2;//p1为移动指针,p2为不断新建的节点
	int i;
	head = (List_Node*)malloc(sizeof(List_Node));
	head->data = NULL;//将头节点的数据置为NULL
	p1 = head;//将头结点的首地址赋给p1
	for (i = 0; i < n; i++)
	{
		cout << "第"<<i<<"个数据" << endl;
		p2 = (List_Node*)malloc(sizeof(List_Node));
		cin >> p2->data;//输入节点的所存储的数据
		p1->next = p2;//将插入的节点的地址赋给上一个节点的链接指针
		p1 = p2;//把节点p2的地址赋给p1,相当于把p1指向的位置后移动一位
	}
	p1->next = NULL;//将最后一个节点的链接指针置为null
	return head;// 返回这个链表的首地址
}

/*------------
打印整个链表
-------------*/
void print(List_Node *L)
{
	List_Node *p;
	p = L->next;
	cout << "输出链表:";
	while (p)
	{
		cout << p->data << ' ';
		p = p->next;
	}
	cout << endl;
}

/*--------------------
	删除指定的节点
----------------------*/
void delete_node(List_Node *L, int x)
{
	List_Node *p = L;
	List_Node *pre;
	while (p->next->data != x && p != NULL)//找到被删除节点的前一个节点
		p = p->next;
	if (p)
	{
		pre = p->next->next;
		free(p->next);
		p->next= pre ;
	}
}

//找到倒数第K个节点,最后一个节点为倒数第一个
List_Node *finde_node(List_Node* pHead, int k)
{
	assert(pHead != NULL);
	// 先获得链表的长度
	int length = 0;
	List_Node* p = pHead;
	while (p != NULL)
	{
		length++;
		p = p->next;
	}
	assert(length >= k);
	p = pHead;
	// 在从头移动 length-k次就好了
	for (int i = 0; i<length - k; i++)
		p = p->next;
	return p;
}

/*--------------------------------------------------------
求单链表倒数第N个数:利用两指针遍历表,保持他们的距离为n,当
后面的指针为NULL时,输出前面指针所指向的数,即倒数第N个数。
----------------------------------------------------------*/
int index_backn(List_Node *L, int n)
{
	List_Node *fir, *sec;
	fir = L->next;
	sec = L->next;
	int i;
	//当i小于n的时候第二个指针移动n步,当i大于等于n时候两个指针一起移动。
	for (i = 0; sec; i++)
	{
		if (n<=i)
		{
			fir = fir->next;
			sec = sec->next;
		}
		else
		{
			sec = sec->next;
		}
	}

	return fir->data;

}

/*------------------------------------------------------------------
找到单链表的中间结点:也是利用两个指针,一个慢移动指针(一次走一步),一
个快移动指针(一次走两步),当快指针指向NULL时,则慢指针指向中间节点。
--------------------------------------------------------------------*/
int find_mid(List_Node *L)
{
	List_Node*fir, *sec;
	fir = L->next;
	sec = L->next;
	while ((sec->next) && (sec->next->next))
	{
		fir = fir->next;
		sec = sec->next->next;
	}
	return fir->data;
}

/*-------------------------------------------------------------------------
链表逆置:利用三个指针来实现的,三个连续指针依
次向前移动,每次反转前两个指针指向数之间的指针
更清楚的一点的解释:通过不断的移动三个指针,每次逆转链接指针的指向,移动到
最后整个链表的链接指向和原来的指向刚好相反,儿节点中数据保持不变,在输出链表
中根据链表的指向输出数据。
---------------------------------------------------------------------------*/
void ReverseList(List_Node *L)
{
	if (!L->next->next)
		;
	else{
		List_Node *p3 = L->next->next->next;
		List_Node *p2 = L->next->next;
		List_Node *p1 = L->next;
		L->next->next = NULL;//将第一个节点的(头结点并不是第一个节点)指针域置为空
		//不断移动两个指针,每次把前两个指针的链接指向逆转
		while (p3){
			p2->next = p1;
			p1 = p2;
			p2 = p3;
			p3 = p3->next;
		}
		p2->next = p1;//移动到最后别忘记把最后一个节点与倒数第二个节点链接上
		L->next = p2;//把头节点链接上最后一个节点
	}
}
//递归的方法逆转链表
List_Node *digui_ReverseList(List_Node *L)
{
	if ((L == NULL) || (L->next == NULL))
		return L;
	List_Node *p1 = L->next;
	List_Node *p2 = L->next->next;
	L=digui_ReverseList(p2);
	p2->next = p1;
	p1->next = NULL;
	return L;
}
/*-----------------------------------
		带头节点表的删除
-------------------------------------*/
List_Node *my_reverse(List_Node *head)
{
	if (head == NULL || head->next == NULL)
		return head;
	List_Node *pre, *cur,*ne;
	pre = head->next;         //将前面几个节点的地址依次保存在新定义的结构体指针
	cur = pre->next;
	while (cur)
	{
		ne = cur->next;
		cur->next = pre;  //直接将两个指针的指向反转
		pre = cur;       //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
		cur = ne;
	}
	head->next->next = NULL; //将原来的第一个节点的指针域赋为空,作为尾节点
	head->next = pre;		//将原来的尾节点变成新链表的第一个节点
	return head;
}


int main()
{
	List_Node *mylist;
	mylist = creat(5);
	//print(mylist);
	//List_Node *p;
	//delete_node(mylist, 3);
	//print(mylist);
	//p=finde_node(mylist, 2);
	//cout << p->data << endl;
	//print(mylist);
	int i,j=0;
	i= index_backn(mylist, 2);
	j = find_mid(mylist);
	cout << i << '\n' << j << endl;
	mylist = my_reverse(mylist);
	//ReverseList(mylist);
	print(mylist);
	return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值