线性表--单链表

#define _CRT_SECURE_NO_DEPRECATE
//#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

#include<iostream>

using namespace std;

typedef struct Node
{
	int data;
	Node *next;
}Node;

Node *headPointer;//头指针
int listLength;//链表长度


/*将头指针加入到参数列表中*/
/* 1.初始化链表,输入数据,数据小于0结束输入。*/
void initList1()
{
	listLength = 0;
	headPointer = new Node;//头指针指向头节点
	if (!headPointer) { cout << "头节点内存分配失败!\n"; exit(0); }
	headPointer->next = nullptr;
	Node *temp = headPointer;//头节点的地址赋给接下来使用的中间变量
	cout << "请输入链表数据(小于0结束输入):\n";
	while (1)//链表赋值
	{
		Node *p = new Node;
		if (!p) { cout << "内存分配失败!\n"; exit(0); }
		cin >> p->data;
		if (p->data < 0) 
		{ 
			delete p; 
			cout << "链表完成!\n";
			return; //结束
		}//数据小于0不可用,需要释放内存
		temp->next = p;
		temp = p;
		temp->next = nullptr;//相当于p->next=nullptr;赋值为空指针,是个好习惯
		listLength++;
	}
	cout << endl;
}

/* 2.在链表的第i个位置之 前 插入数据e */
void insertBefore(int i, int e)
{
	cout << "在链表第" << i << "个位置前插入数据" << e << endl;
	if (i<1 || i>listLength) { cout << "数据插入位置错误!\n"; return; }
	Node *p = headPointer;
	Node *temp = new Node;//申请新内存
	if (!temp) { cout << "内存分配失败!\n"; exit(0); }
	while (--i) 
		p = p->next;//找到第i-1个位置
	temp->data = e;
	temp->next = p->next;
	p->next = temp;
	listLength++;
	cout << "链表长度为:" << listLength << "  数据插入成功!\n";
}

/*在链表第i个位置之 后 插入数据e*/
void insertAfter(int i, int e)
{
	cout << "在链表第" << i << "个位置之后插入数据" << e << endl;
	if (i<1 || i>listLength) { cout << "数据插入位置错误!\n"; exit(0); }
	Node *p = headPointer;
	Node *temp = new Node;//申请新内存
	if (!temp) { cout << "内存分配失败!\n"; exit(0); }
	while (i--) 
		p = p->next;
	temp->data = e;
	temp->next = p->next;
	p->next = temp;
	listLength++;
	cout << "链表长度为:" << listLength << "  数据插入成功!\n";
}

/* 4. 删除链表的第i个位置的数据 */
bool deleteList(int i)
{
	cout << "删除链表第" << i << "个位置的数据\n";
	Node *p = headPointer;
	while (--i) p = p->next;//找到第i-1个位置
	Node *deleteTemp = p->next;//为第i个位置的内存释放做准备
	p->next = p->next->next;
	delete deleteTemp;
	listLength--;
	cout << "链表长度为:" << listLength << "  数据删除成功!\n";
	return true;
}

/* 5.打印链表所有数据 */
bool printList()
{
	if (headPointer->next == nullptr)
	{
		cout << "链表为空!\n";
		return false;
	}
	cout << "链表长度为:" << listLength << "打印链表:\n";
	Node *p = headPointer;
	while (p->next != nullptr)
	{
		cout << p->next->data << " ";
		p = p->next;
	}
	cout << "链表打印成功!\n\n";
	return true;
}

/* 6. 清除链表*/
bool clearList()
{
	if (headPointer->next == nullptr)
	{
		cout << "链表为空,无法再清除!\n";
		return false;
	}
	Node *p = headPointer;
	Node *temp;
	while (p != nullptr)
	{
		temp = p->next;
		delete p;
		p = temp;
		listLength--;
	}
	cout << "链表清除成功!\n" << "链表长度为" << listLength + 1 << endl;//头节点不计入链表长度,而清除链表时,头节点也被清除
	return true;
}

/* 7.返回链表中第i个结点中的数据的地址*/
int* getData(int i)
{
	if (i<1 || i>listLength) { cout << i << "值超出链表范围!\n"; return false; }
	Node *p = headPointer;
	while (i--) p = p->next;
	return &(p->data);
}

/* 8. 给定数值,判断链表中是否存在该数值,如果存在返回数值相同的第一个结点的地址*/
Node* findList(int e)
{
	Node *p = headPointer;
	while (p->next != nullptr)
	{
		p = p->next;
		if (p->data == e) return p;
	}
	return nullptr;
}

/* 9. 修改链表中第i个结点的数据*/
bool modifyList(int i, int e)
{
	if (i<1 || i>listLength) { cout << "修改的结点位置错误!\n"; return false; }
	Node *p = headPointer;
	while (i--) p = p->next;
	p->data = e;
	return true;
}

/* 10. 逆位序输入n个元素的值*/
void initList2(int n)
{
	headPointer = new Node;//头指针指向头节点
	headPointer->next = nullptr;
	while (n--)
	{
		Node *p = new Node;
		if (!p) { cout << "内存分配失败!\n"; exit(0); }
		cin >> p->data;
		p->next = headPointer->next;
		headPointer->next = p;
	}
}

/* 11. 按顺序归并两个链表*/
bool mergeList(Node*  &a, Node*  &b, Node*  &c)
{
	Node *pa = a->next;
	Node *pb = b->next;
	Node *pc = c = a;//把a的头节点给c,最后要删除b的头节点
	while (pa&&pb)
	{
		if (pa->data <= pb->data)
		{
			pc->next = pa;
			pc = pa;
			pa = pa->next;
		}
		else
		{
			pc->next = pb;
			pc = pb;
			pb = pb->next;
		}
	}
	pc->next = pa ? pa : pb;
	delete b;
	return true;
}

/*12.交换两个节点的data*/
void swapList(Node *i,Node *j)
{
	int temp = i->data;
	i->data = j->data;
	j->data = temp;
}

/* 13. 链表排序*/
//pStart指向首个元素的节点,不是头节点;pEnd是null,也就是最后一个节点的next
void sortList(Node *pStart,Node *pEnd)
{
	if (pStart == pEnd||pStart->next==pEnd)
		return;
	//这里的第一个节点不是头节点,而是头节点的下一个节点,依次类推
	int dataBase = pStart->data;

	Node *firstNode = pStart;//保存第一个节点(也就是头节点的下一个节点)
	Node *i = pStart;
	Node *j = pStart->next;//指向第二个节点

	while (j != pEnd)
	{
		if (j->data < dataBase)
		{
			i = i->next;
			swapList(i, j);
		}
		j = j->next;
	}
	swapList(firstNode, i);
	sortList(pStart, i);
	sortList(i->next, pEnd);
}

/*14.已知线性表数据递增有序,删除表中所有值大于mink且小于maxk的数据,并释放被删除的结点*/
bool deleteYouWant1(int mink, int maxk)
{
	Node *p = headPointer;
	while (p->next != nullptr)//先判断
	{
		if (p->next->data>mink)//先找到满足条件的点然后删除,而不是指针已指向满足条件的点才去删除
		{
			if (p->next->data >= maxk)
				return true;
			Node *willDelete = p->next;
			p->next = p->next->next;
			delete willDelete;
			listLength--;
		}
		else
			p = p->next;
	}
	return false;
}

/*15.已知线性表数据递增无序,删除表中所有值大于mink且小于maxk的数据,并释放被删除的结点*/
void deleteYouWant2(int mink, int maxk)
{
	Node *p = headPointer;
	while (p->next != nullptr)
// p->next != nullptr 先判断,而不是 p!= nullptr,因为你下面是提前判断数据data,如果
//不提前判断是不是nullptr,下面的数据判断可能造成非法访问data的错误
	{
		if (p->next->data > mink && p->next->data < maxk)
		{
			Node *willDelete = p->next;
			p->next = p->next->next;
			delete willDelete;
			listLength--;
		}
		else
			p = p->next;
	}
}

/*16.删除数据相同的节点,仅只保留一个*/
void uniqueList1()
{
	Node *p = headPointer->next;
	while (p != nullptr)
	{
		Node *temp = p->next;
		Node *frontNode = p;//保留我要删除的节点的上一个节点,以便删除节点时,将前后两个节点相接
		while (temp!=nullptr)
		{
			if (temp->data == p->data)
			{
				Node *willDelete = temp;

				frontNode->next = temp->next;
				temp = temp->next;

				delete willDelete;
				listLength--;
			}
			else
			{
				frontNode = temp;
				temp = temp->next;
			}
		}
		p = p -> next;
	}
}

/*17.删除数据相同的节点,仅只保留一个*/
void uniqueList2()//和上面的版本不一样之处就是,没有frontNode指针保留前一个结点,而是采用先判断再去删除的办法
{
	Node *p = headPointer;
	while (p != nullptr)
	{
		Node *temp = p;
		while (temp->next != nullptr)//temp->next != nullptr采用先判断再去删除的办法,而不是temp!=nullptr
//进行删除操作时,我们是肯定是要知道删除节点的上一个节点,要不我们每走一步,保留上一个节点,
//要不在删除节点的前面停下来uniqueList2采用的是后者
		{
			if (temp->next->data == p->data)
			{
				Node *willDelete = temp->next;
				temp->next = temp->next->next;
				delete willDelete;
				listLength--;
			}
			else
				temp = temp->next;
		}
		p = p->next;
	}
}


int main()
{
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值