#include <iostream>
#include <Windows.h>
using namespace std;
//定义一个链表
typedef struct _Linknode {
int data; //节点的数据域
struct _Linknode* next; //节点的指针域
} Linklist, Linknode;//1. 表示首节点 2.表示节点
//初始化链表
bool Initlist(Linklist* &list) {
//这里是意思是创建一个首节点
//
list = new Linknode;
if (!list) {
return false; //如果分配内存失败结束程序返回假
}
list->next = NULL;
return true;
}
//前插法
bool Listinsert(Linklist* &list, Linknode* &node) {
if (!list || !node) {
cout << "list或者node为空,程序结束";
return false;
}
//前插法 把首节点的next 赋值给 新节点的next(如果只有一个首节点那么新节点的next指向为空)
//然后把首节点next指向 新节点本身 以此类推创建多个节点
node->next = list->next;
list->next = node;
return true;
}
//后插法插入链表
bool listInsert_back(Linklist* &list, Linknode* &node) {
Linknode* last = NULL;
if (!list || !node) {
cout << "返回false,程序结束";
system("pause");
return false;
}
last = list->next;
while (last->next) {
//如果last的next不为空的话 一直赋值给下一个节点
//如果last的next指针为空的话 说明已经找到最后一个节点了
//那么就循环条件不成立了
last = last->next;
}
//找到最后一个节点后 要在最后一个节点后插入节点
//那么就是把 last(上次循环找到的最后一个节点) 指向要插入的新节点
//然后把新插入节点的next指向空. 以此类推
last->next = node;
node->next = NULL;
return true;
}
// 由用户任意指定位置插入节点
//需要传递三个参数1. 首节点 2.要插入的节点的位置int i 3.要插入节点的数据 int e
bool linkInsert_rand(Linklist*& list, int i, int e) {
if (!list) {
return false;
}
int j = 0; //用于计数 找到要新插入节点的位置
Linknode* p = NULL; //临时指针
Linknode* s = NULL; //要插入的新节点的指针
//要想实现在任意位置插入节点的话 那么就要先找到插入节点的位置
//方法就是 先创建一个临时指针P 先指向首节点 然后while循环
//如果节点的位置是5 那么要插入的节点位置就是5-1
//小学数学问题 要插入的位置是 n的话 那么他的位置就是n-1
p = list; //从首节点开始找
//就是要插入的节点在哪个位置 就循环多少次
while (p && (j < i - 1)) { //判断指针p不为空 而且 j<i-1 来控制循环次数
p = p->next;
j++;
}
//如果 i=负数 的话 那么上面while循环的j永远不会i-1 那么循环会一直进行
// p为NULL 也就是到最后一个节点... 那么这个时候就是非法的了
//如果用户输入的数据大于已有节点的数量 p会一直遍历到最后一个节点 导致p=NULL
//那么就需要下面的防御性检查了...
//合法性检查 如果p为空的话 说明插入的位置已经超过节点数量了
//那么就是非法的 或者用户输入的插入位置小于0
if (!p || j > i - 1) {
return false;
}
s = new Linknode; //前面找到为插入节点的位置以后 新节点传入数据
s->data = e;
s->next = p->next; //新节点的next指向 插入点位置前面节点的next(p->next)
p->next = s; //然后再把前面位置节点(p->next)指向新节点本身
return true;
}
//查找链表数据 (按位置查找)
bool link_GetElem(Linklist*& list, int i, int& e) {
int index = 0; //用于计数
Linklist* p = NULL; //临时指针用来遍历链表
if (!list || !list->next) {
return false; //如果list为空 那么就说明没有任何节点
//或者list.next为空 说明只有一个节点 那么就没必要查找了
}
index = 1;
p = list->next;
while (p && index < i) {
p = p->next;
index++;
}
if (!p || index > i) { //防止p为空 或者 用户输入非法的位置 把程序搞崩
return false;
}
e = p->data;
return true;
}
//查找链表数据 (按值查找)
bool link_FindElem(Linklist*& list, int e,int &index) {
Linklist* p = NULL;
index = 1;
if (!list || !list->next) {
index = 0;
return false;
}
p = list->next;
while (p && p->data != e) { //p不能为空, 遍历链表如果数据不是要查找的数据
//那么p就移向下一个节点
p = p->next;
index++;
}
if (!p) { //如果p为空 那么就说明遍历链表全部数据了 然后查无此值
index = 0; //p遍历到链表的全部数据才会为空 因为最后一个节点next是空
return false;
}
return true;
}
//删除链表的节点
bool linkDelete(Linklist*& list,int i) {
Linklist* p = NULL; //临时指针用来遍历链表
Linklist* q = NULL; // 保存要被删除的节点
int index = 0;
p = list;
while (p->next && index < i - 1) {
p = p->next;
index++;
}
if (!p || index > i - 1) { //p为空或者index大于i-1删除位置不合法
return false;
}
q = p->next; //临时保存要被删除的节点 以后用来delete
p->next = q->next; //p的next指向被删除节点的下一个节点
delete q;
return true;
}
//单链表的销毁
void linkDestroy(Linklist*& list) {
Linklist* p = NULL;
cout << "销毁链表!!" << endl;
p = list;
while (p) {
list = list->next; //list指向下一个节点
delete p; //删除当前节点
p = list;
}
}
//遍历链表数据(打印链表)
//需要传入首节点 根据首节点 找到后面的节点
void linkPrint(Linklist*& list) {
Linknode* p = NULL;
if (!list) {
cout << "链表为空";
return;
}
//遍历链表数据首先建立一个临时指针然后指向首节点的next
//然后循环遍历 因为节点本身的next就是指向下一个节点的
//所以 通过每个节点的next 来访问下一个节点
//只需要把每个节点的next 赋值给 临时指针p 然后逐次打印每个节点的data
// 那么就实现了遍历真个链表
p = list->next;
int i = 1;
while (p) { // 如果下一个节点的next为空 那么就是最后一个节点了 那么结束循环停止遍历
cout <<"节点"<<i++<<"数据:"<< p->data << endl; //打印当前指向节点的数据
p = p->next; //p赋值给下一个节点的指针
}
}
int main(void) {
cout << "--------单向链表的算法实现--------" << endl;
Linklist* list= NULL;
Linknode* s = NULL;
//1.初始化一个单链表
Initlist(list);
//2.使用前插法插入数据
cout << "1.------使用前插法插入节点------" << endl;
int n;
cout << "前插法创建单链表:";
cin >> n;
cout << "请以此输入n个元素:";
while (n > 0) {
//每循环一次就创建一个linknode类型的动态内存表示创建一个节点
//然后让用户输入data 然后再调用插入函数 把每个节点链接起来
s = new Linknode;//创建新的节点
cin >> s->data;
Listinsert(list, s);
n--;
}
//遍历链表 打印数据
linkPrint(list);
//3. 使用后插法插入节点
cout << "2.------使用后插法插入节点---------"<<endl;
cout << "后插法创建单链表:";
cin >> n;
cout << "请以此输入n个元素:";
while (n > 0) {
s = new Linknode;//创建新的节点
cin >> s->data;
listInsert_back(list, s);
n--;
}
//遍历链表 打印数据
linkPrint(list);
//4. 任意位置插入节点'
cout << "3.------任意位置插入节点------" << endl;
int i, e;
cout << "请输入插入节点的位置:";
cin >> i;
cout << "请输入要插入节点的data(数据):";
cin >> e;
if (linkInsert_rand(list, i, e)) {
cout << "插入成功!!" << endl;
}
else {
cout << "插入失败!!" << endl;
}
linkPrint(list);
//5. 查找链表的数据(按位置查找值)
int elems = 0;
if (link_GetElem(list, 2, elems)) {
cout << "获取第二个元素成功,值为:" << elems << endl;
}
else {
cout << "获取失败!!" << endl;
}
//6. 查找链表的数据(按值查找 并返回位置)
int index = 0;
if (link_FindElem(list, 100, index)) {
cout << "找到数据100存在,位置在:" << index << endl;
}
else {
cout << "查无此值!!" << endl;
}
//7. 单链表节点的删除
if (linkDelete(list, 2)) {
cout << "删除成功!!" << endl;
}
else {
cout << "删除第二个节点失败" << endl;
}
linkPrint(list);
//8. 单链表的销毁
linkDestroy(list);
system("pause");
return 0;
}
单向链表的算法实现
最新推荐文章于 2022-05-15 10:45:28 发布