头节点->第一个节点->第二个节点->第三个节点->…->第n个节点(尾节点)->NULL
//单链表
#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
typedef struct _LinkNode {
int date;//结点的数据域
struct _LinkNode* next;//结点的指针域
}LinkNode,LinkList;//链表结点,链表
bool InitList(LinkList* &L) {//构造一个空的单链表
//L是一个LinkList*类型的引用
L = new LinkNode;//生成新结点作为头结点,用头指针L指向头结点
if (!L)return false;//生成结点失败
L->next = NULL;//头结点的指针域置空
L->date = -1;//头结点没有值,这里可以赋值成-1
return true;
}
前插法 =>依次把元素插在前面
//bool ListInsert_front(LinkList* &L, LinkNode* node) {
// if (!L || !node)return false;
// node->next = L->next;//左边是橄榄枝,右边人才本身
// L->next = node;//左边是橄榄枝,右边人才本身
// return true;
//}
//尾插法 =>依次把元素插在后面(只要找到最后一个元素即可)
bool ListInsert_back(LinkList* &L, LinkNode* node) {
LinkNode* last = NULL;
if (!L || !node)return false;
last = L;
while (last->next) last = last->next;//依次遍历找到最后一个节点(最后一个节点的特点:
//最后一个节点的next为空)
node->next = NULL;//左边是橄榄枝,右边人是受邀人
last->next = node;//左边是橄榄枝,右边是受邀人
return true;
}
//单链表的输出
void LinkPrint(LinkList* &L) {
cout << "链表输出:" << endl;
LinkList* p = NULL;//用一个临时指针来遍历
if (!L) {
cout << "链表为空." << endl;
return;
}
p = L->next;
while (p) {
cout << p->date << "\t";
p = p->next;
}
cout << endl;
//delete p; => 没有new怎么能用delete呢?
}
//在任意位置的插入
//指定位置插入
//也叫前插法
bool LinkInsert(LinkList* &L,int i,int &e) {//在位置i插入元素e
if (!L) return false;
int j = 0;
LinkList* p, * s;
p = L;
//找到位置为i-1的节点,p指向该节点
while (p && j < i - 1) {//当p不为空且j<i-1
p = p->next;
j++;
}
//要在节点2插入一个元素,就要找到节点1(节点和位置在数值上保持一致)
// eg:在节点2插入一个元素
//第一轮循环:0<2-1 =>p从头节点指向第一个节点
//第二轮循环:1<1 =>不成立,循环结束
if (!p||j>i-1) {
//!p 防止出现你只有3个节点,但是你想在第5个节点插入的现象
//j>i-1 防止你想在负位置插入(防止i=0和i<0的情况)(因为节点最小是1)
return false;
}
//如果能走到这,说明已经 找到了 要插入位置 的 前一个节点 了
s = new LinkNode;//生成新节点
s->date = e;
s->next = p->next;
p->next = s;
return true;
//malloc一次free一次,new一次delete一次
//函数调用完毕之后,堆空间是不会自动消失的!
//函数调用完毕之后,指针变量s(存放在栈空间)没了,但是,之前申请的堆空间还在
//=>也就是说,函数调用完毕之后,没有任何人指向之前申请的堆空间了,但是,内存,还在!
delete s;
}
//单链表的取值
// 也叫按位查找
//按位置获取对应位置的元素
bool Link_GetElem(LinkList*& L, int i, int& e) {
//在链表中查找第i个元素
//用e记录链表第i个数据元素的值
int index;
LinkList* p;//临时的指针
if (!L || !L->next) return false;
//链表为空,或者只有一个头结点,直接return false
p = L->next;
index = 1;
while (p&&index<i) {
//p不为空,当index==i时,就找到了
p = p->next;
index++; //计数器相应+1
}
if (!p || index > i) return false;//i值不合法,i>n或者i<=0
e = p->date;
return true;
}
//按值查找
bool Link_FindElem(LinkList *L,int e,int &index) {
//在带头结点的单链表L中查找值为e的元素
//并返回元素e的位置index
LinkList* p;//临时的指针
p = L->next;//让p指向第一个节点
index = 1;
if (!L || !L->next) {
//链表为空,或者只有一个头结点,直接return false
index = 0;//位置无效
return false;
}
while (p && p->date != e) {
//p不为空,当p->date == e时,就找到了
p = p->next;
index++;
}
if (!p) {
//查无此值
index = 0;//位置无效
return false;
}
return true;
}
//单链表删除元素
bool LinkDelete(LinkList*& L, int i) {
//删除节点i
//要删除第二个节点,就要找到第一个节点
LinkList* p, * q;
int index = 0;
p = L;//从头结点开始
if (!L || !L->next) {
return false;
}
while (p->next && index < i - 1) {
p = p->next;
index++;
}
if (!p->next || index > i - 1) {//当i>n或i<1时,删除位置不合理
return false;
}
q = p->next;//这里q并没有抛出橄榄枝,然而直接把q变成了p->next本身
p->next = q->next;//左边是橄榄枝,右边是受邀人(只有左边是->next时,才是抛出橄榄枝)
delete q;//释放删除节点q的内存
return true;
}
//销毁单链表
void LinkDextory(LinkList* &L) {
//定义临时节点p指向头结点
LinkList* p = L;
cout << "正在销毁单链表..." << endl;
while (p) {
L = L->next;//L指向下一个节点
cout << "删除元素:" << p->date << endl;
delete p;//删除当前节点
p = L;//p移向下一个节点
}
cout << "销毁单链表成功!" << endl;
}
int main() {
LinkList* L = NULL;//L作为主体链表
LinkList* s = NULL;//s作为要插入的新链表
//初始化一个空的链表
InitList(L);
cout << "初始化链表成功" << endl;
//使用前插法插入数据
//int n;
//cout << "前插法创建单链表" << endl;
//cout << "请输入n个元素:";
//cin >> n;
//cout << "\n请依次输入n个元素" << endl;
//while (n > 0) {
// s = new LinkNode;//生成新结点s //新结点指针域
// cin >> s->date; //新结点数据域
// ListInsert_front(L, s);
// n--;
//}
//使用尾插法插入数据
int n;
cout << "尾插法创建单链表!" << endl;
cout << "请输入您要创建元素的个数:";
cin >> n;
cout << "\n请依次输入" << n << "个元素" << endl;
while (n > 0) {
s = new LinkNode;//生成新结点s //新结点指针域
cin >> s->date; //新结点数据域
ListInsert_back(L, s);
n--;
}
//单链表的输出
LinkPrint(L);
//任意位置插入
printf("这里插入3次.\n");
for (int j = 0; j < 3; j++) {
int i, x;
cout << "请输入要插入的位置和元素(用空格隔开):" << endl;
cin >> i >> x;
if (LinkInsert(L, i, x)) {
cout << "插入成功\n";
}
else {
cout << "插入失败哦\n";
}
LinkPrint(L);
}
int element = 0;
if (Link_GetElem(L, 2, element)) {
cout << "获取第二个元素成功! 值: " << element << endl;
}
else {
cout << "获取第二个元素失败哦!" << endl;
}
int index = 0;
if (Link_FindElem(L, 10, index)) {//查找元素10的位置
cout << "查找元素10的位置是:" << index << endl;
}
else {
cout << "查无此值" << endl;
}
if (LinkDelete(L, 2)) {
cout << "删除第2个元素成功!" << endl;
LinkPrint(L);
}
else {
cout << "删除第2个元素失败" << endl;
LinkPrint(L);
}
LinkDextory(L);
system("pause");
return 0;
}