//带头结点
#include <iostream>
#include "stdlib.h"
using namespace std;
struct Node
{
int data;
struct Node* next;
};
//初始化
int initList(Node** head)
{
*head = new Node; //生成一个头结点,将头指针指向这个头结点
(*head)->next = nullptr; //将头结点的指针域置空
return 1;
}
//判断链表是否为空
int isEmpty(Node* head)
{
if (head && head->next) //带头结点则判断头结点的指针域,不带头结点则判断首元结点的指针域。两者都表示为head->next
return 0;
else
return 1;
}
//销毁链表
int destroyList(Node** head)
{
while (*head) //3.当head指向最后一个节点(虽然指针域head->next为空,但还是有数据,所以不能不管了,还得释放这个节点)时,不能用判断条件while(head->next),head还得往后移,直到head指向空。
{
Node* p = *head; //1.先将头结点保存给p
*head = (*head)->next; //2.然后将头结点保存下一个节点的地址,不然销毁p后就找不到下一个节点了,因为下一个节点的地址保存在head节点的指针域中
delete p; //5.p来销毁当前结点,head来遍历(保存当前要销毁的结点的下一个结点的地址)
}
return 1; //4.包括头结点以及其他所有结点都被销毁掉了
}
//清空链表
int clearList(Node* head)
{
if (head == nullptr) return 0;
Node* p = head->next; //1.先将p保存首元结点的地址
while (p)
{
Node* q = p->next; //2.保存当前要销毁的结点的下一个结点的地址
delete p; //3.p来销毁当前结点,q来遍历(保存当前要销毁的结点的下一个结点的地址)
p = q; //4.销毁后将p往后移
}
head->next = nullptr; //5.将头结点的指针域置空
return 1; //6.清空所有元素节点,保留头结点,并将头结点指针域置空
}
//获取链表的长度
int getListLength(Node* head)
{
if (head == nullptr) return 0;
int length = 0;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。当前p指向首元结点。
while (p) //2.当p指向最后一个节点(虽然指针域p->next为空,但length还没++)时,不能用判断条件while(p->next),p还得往后移,直到p指向空。
{
length++;
p = p->next; //当p指向最后一个结点时,p->next为空,赋值给p,则p为空了。如果是一个空表,则head->next为空,赋值给p,则直接退出循环。
}
return length;
}
//获取第i个元素
int getValue(Node* head, int index, int& value)
{
if (head == nullptr) return 0;
if (index < 1)return 0;
int i = 0;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。将p指向首元结点。
while (p)
{
i++;
if (i == index)
{
value = p->data;
return 1;
}
p = p->next;
}
return 0;
}
//查找值并返回位置
int findListPos(Node* head, int value, int& index)
{
if (head == nullptr) return 0;
int i = 0;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。将p指向首元结点。
while (p)
{
i++;
if (p->data == value)
{
index = i;
return 1;
}
p = p->next;
}
return 0;
}
//查找值并返回这个结点
Node* findList(Node* head, int value)
{
if (head == nullptr) return 0;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。将p指向首元结点。
while (p)
{
if (p->data == value)
{
break;
}
p = p->next;
}
return p;
}
//在第i个结点前插入一个新结点
int insert(Node* head, int index, int value)
{
if (head == nullptr) return 0;
int i = 0;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。将p指向首元结点。
if (p == nullptr) //空表
{
Node* node = new Node; //生成一个新结点
node->data = value;
node->next = nullptr;
head->next = node;
return 1;
}
else
{
Node* q = head; //2.保存当前结点p的上一个结点的地址(当插入的是第1个结点前时q指向head,而不是空)
while (p)
{
i++;
if (i == index)
{
Node* node = new Node; //3.生成一个新结点
node->data = value;
node->next = p; //4.新结点的指针域保存当前要插入的结点p的地址
q->next = node; //5.将新结点的地址保存到当前要插入的结点p的上一个结点的指针域
return 1;
}
q = p; //6.保存当前结点p的上一个结点的地址
p = p->next;
}
}
return 0;
}
//向链表后面依次添加新结点
int addList(Node* head, int value)
{
if (head == nullptr) return 0;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。将p指向首元结点。
if (p == nullptr) //空表
{
Node* node = new Node; //生成一个新结点
node->data = value;
node->next = nullptr;
head->next = node;
}
else
{
while (p->next) //当遍历到最后一个结点时p->next为空,则p为最后一个结点
{
p = p->next;
}
Node* node = new Node; //生成一个新结点
node->data = value;
node->next = nullptr;
p->next = node;
}
return 1;
}
//删除第i个结点(方法一)
int deleteNode(Node* head, int index)
{
if (head == nullptr) return 0;
if (index < 1)return 0;
int i = 0;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。将p指向首元结点。
Node* q = head; //2.q保存p上一个结点的地址
while (p)
{
i++;
if (i == index)
{
q->next = p->next; //3.将当前结点p的前一个结点q的指针域保存p的下一个结点的地址(p->next)
delete p;
return 1;
}
q = p;
p = p->next;
}
return 0;
}
//删除第i个结点(方法二)
int deleteNode_(Node* head, int index)
{
if (head == nullptr) return 0;
if (index < 1)return 0;
int i = 0;
Node* p = head; //注意这里!!!
while (p)
{
if (i == index - 1) //1.首先找到a(i-1)的存储位置p
{
Node* deleteNode = p->next; //2.改变指针域前先保存要删除的a(i)的地址以便删除
p->next = p->next->next; //3/将要删除的a(i)结点的前一个结点a(i-1)(也就是p)的指针域指向a(i)的下一个结点
delete deleteNode;
return 1;
}
i++;
p = p->next;
}
return 0;
}
//遍历输出
void showList(Node* head)
{
if (head == nullptr) return;
Node* p = head->next; //1.不能直接通过head来遍历,这样会改变链表,需要通过p来遍历。将p指向首元结点。
while (p)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
//头插法建立单链表
int insertFront(Node** head, int value)
{
if (*head == nullptr)
{
//生成头结点
*head = new Node;
(*head)->data = 0;
(*head)->next = nullptr;
}
//新建一个结点
Node* node = new Node;
node->data = value;
node->next = (*head)->next;
(*head)->next = node; //头插法只插在头结点的后面
return 1;
}
//尾插法建立单链表
int insertBack(Node** head, int value)
{
if (*head == nullptr)
{
//生成头结点
*head = new Node;
(*head)->data = 0;
(*head)->next = nullptr;
}
return addList(*head, value);
}
void main()
{
Node* head = nullptr;
initList(&head);
int ret = isEmpty(head);
cout << (ret == 1 ? "链表为空" : "链表不为空") << endl;
//for (int i = 0; i < 10; i++)
// insert(head, i + 1, i); //当i=0时,要插入的位置为1,head为空表,则生成一个新结点,。当i=1时,要插入的位置为2,但表还只有1个结点,则插入失败,后面也是。
//insert(head, 0, 0);
//insert(head, 1, 1);
//insert(head, 2, 2);
for (int i = 0; i < 10; i++)
addList(head, i);
insert(head, 3, 100);
cout << "在第3个结点前插入新结点100" << endl;
showList(head);
deleteNode(head, 3);
cout << "删除第3个结点" << endl;
showList(head);
deleteNode_(head, 3);
cout << "删除第3个结点" << endl;
showList(head);
for (int i = 99; i < 109; i++)
insertFront(&head, i);
cout << "头插法插入结点:" << endl;
showList(head);
ret = isEmpty(head);
cout << (ret == 1 ? "链表为空" : "链表不为空") << endl;
int length = getListLength(head);
cout << "链表的长度:" << length << endl;
int value = 0;
getValue(head, 3, value);
cout << "第3个元素的值为:" << value << endl;
Node* p = findList(head, 8);
cout << "第8个结点的值为:" << p->data << endl;
int index = 0;
findListPos(head, 9, index);
cout << "值为9的位置:第" << index << "个元素" << endl;
clearList(head);
cout << "清空列表!" << endl;
ret = isEmpty(head);
cout << (ret == 1 ? "链表为空" : "链表不为空") << endl;
for (int i = 0; i < 10; i++)
addList(head, i);
showList(head);
ret = isEmpty(head);
cout << (ret == 1 ? "链表为空" : "链表不为空") << endl;
destroyList(&head);
cout << "销毁列表!" << endl;
ret = isEmpty(head);
cout << (ret == 1 ? "链表为空" : "链表不为空") << endl;
Node* head_ = nullptr;
for (int i = 10; i < 20; i++)
insertBack(&head_, i);
cout << "尾插法插入结点:" << endl;
showList(head_);
for (int i = 99; i < 109; i++)
insertFront(&head_, i);
cout << "头插法插入结点:" << endl;
showList(head_);
for (int i = 0; i < 9; i++)
addList(head_, i);
cout << "尾插法插入结点:" << endl;
showList(head_);
for (int i = 88; i < 99; i++)
insertBack(&head_, i);
cout << "尾插法插入结点:" << endl;
showList(head_);
}