#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;
}
线性表--单链表
最新推荐文章于 2023-04-20 20:24:30 发布