数据结构与算法单链表

mac2024-07-24  58

数据结构与算法 单链表

单链表

单链表是一种线性结构,单链表存储分成两部分,一部分存储数据,另一部分存储下一个节点(也就是指向下一个链表的地址(单指向))的地址。

1.定义链表,初始化链表

创建头节点,指针域置空。—代码注释为详细内容

//结构体定义链表 typedef struct _LinkNode { int data; //数据域(存储数据) struct _LinkNode* next; //指针节点,指向(存储)下个链表节点的地址 }LinkNode,LinkList; 链表节点、链表 //初始化链表,定义头节点 bool InitList(LinkList* &L) { //构造一个空的单链表 L L = new LinkNode; //创建新结点作为头结点,用头指针L指向头结点 if (!L) { cout << "初始化链表失败!" << endl; return false;//生成结点失败 } L->next = NULL; //头结点的指针域置空 cout << "初始化链表成功!" << endl; return true; }

2.单链表增加元素(前插法)

头节点后为每次插入的新节点,先插后出(最先插入的节点的节点元素,输出时则在最后面)

//前插法 bool ListInsert_front(LinkList*& L, LinkNode* node) {//L为头节点,node为新节点(子节点) if (!L || !node) return false;//防止链表为空 node->next = L->next;//将头节点指向的下一个节点的地址赋值给新节点 L->next = node; //将头节点指针指向新节点的地址 return true; }

3.尾插法

循环找出最后一个节点,然后在该位置插入,原最后节点指针指向新节点,新节点指针设置为空。

//尾插法 bool ListInsert_back(LinkList*& L, LinkNode* node) { LinkNode* last = NULL; if (!L || !node) return false;//判断是否为空 last = L;//指向头链表,将头链表的地址赋给last指针 //通过循环找到最后一个(节点)链表,即指针域存储为NULL的链表 while (last->next) last = last->next;//如果链表中next指针不为空,那么就指向下一个链表的地址 node->next = NULL;//将新节点的指针域设置为空 last->next = node;//将原链表中最后一个节点的指针指向新链表的地址 return true; }

4.任意位置插入法

通过循环找出要插入位置的节点,然后将(要插入位置的)前节点指针指向新节点的地址,再将新节点指针指向(i+1)的节点的地址。

//任意位置插入 bool LinkInsert(LinkList*& L, int i, int& e) { //在单链表L中,在第i个位置插入元素e if (!L) return false; //判断是否为空 int j = 0; LinkList* p, * s; p = L; //指针p指向头节点 //找出要插入节点位置的前一个结点 while (p && j < i - 1) {//查找位置为i-1的节点,p指向该节点 p = p->next; j++; } if (!p || j > i - 1) {//判断p是否为空或者i值是否合法 return false; } s = new LinkNode;//生成新节点 s->data = e;//把插入的元素值赋值给新结点的数据域 s->next = p->next;//将新节点指针指向原i节点的地址 p->next = s;//将原(i-1)节点指针指向新节点地址 return true; }

5.获取单链表中的元素

通过要查找的位置i循环查找链表,找到后把元素值赋值给e。

//单链表的取值 bool Link_GetElem(LinkList* &L,int i,int &e) { //在带头结点的单链表L中查找第i个元素(i为查找的元素位置) //用e记录L中第i个数据元素的值(e为被查找的元素值) int index; LinkList* p; if (!L || !L->next) return false; //判断是否为空 p = L->next;//p指向第一个节点 index = 1; //计数器,记录当前为哪一个节点(链表) while (p && index<i) {//链表依次向后扫描,直到指针p指向所指i个元素或者p为空 p = p->next; //p指向下一个节点(下一个链表的地址) index++; //每循环一次index加1 } if (!p || index > i) { return false; //要查询的元素个数i不合法,i>n或i<=0 } e = p->data;//将被查找节点的元素赋值给e return true; }

6.单链表查找元素

循环判断该节点元素值是否与要查找元素值相等。

//单链表查找元素(查询) bool Link_FindElem(LinkList* L, int e, int &index) {//按值查找 //在带头结点的单链表L中查找值为e的元素 LinkList* p; p = L->next; //指针p指向第一个节点 index = 1; //计数器 if (!L || !L->next) { index = -1; return false; }//判断是否为空 while (p && p->data != e) { //判断该节点元素值是否与要查找元素值相等 p = p->next; index++; //该节点位置 } if (!p) { index = -1; return false;//查无此值 } return true; }

7.单链表中元素的删除(通过位置删除)

被删除节点要释放内存空间

//单链表中元素的删除 bool LinkDelete(LinkList*& L, int i) {//i为要删除节点的位置 LinkList* p,*q; int index = 0; p = L;//将指针p指向头节点(链表) if (!L || !L->next) { return false; }//判断是否为空 //判断p指针是否为空 要删除节点位置i是否合法 while ((p->next) && (index < i - 1)) {//循环查找i节点 p = p->next; index++; } if (!p->next || (index > i - 1)) {//当i>n或者i<1时,删除位置不合理 return false; } q = p->next; //临时保存被删除节点的地址以备释放空间 p->next = q->next; //将(被删除节点)的前节点的指针指向(被删除节点)的后节点的地址 delete q; //释放被删除节点的空间 return true; }

8.单链表的销毁

通过循环释放内存空间,完成销毁。

//单链表的销毁 void LinkDestroy(LinkList*& L) { //定义临时节点p指向头节点 LinkList* p = L; //将指针p指向头节点(链表) cout << "销毁链表" << endl; while (p) { L = L->next;//L指向下一个节点 delete p; //删除当前节点 p = L; //p移向下一个节点 } }

9.完整代码

#include <iostream> #include <string> #include <stdlib.h> using namespace std; //结构体定义链表 typedef struct _LinkNode { int data; //数据域(存储数据) struct _LinkNode* next; //指针节点,指向(存储)下个链表节点的地址 }LinkNode,LinkList; 链表节点、链表 //初始化链表,定义头节点 bool InitList(LinkList* &L) { //构造一个空的单链表 L L = new LinkNode; //创建新结点作为头结点,用头指针L指向头结点 if (!L) { cout << "初始化链表失败!" << endl; return false;//生成结点失败 } L->next = NULL; //头结点的指针域置空 cout << "初始化链表成功!" << endl; return true; } //前插法 bool ListInsert_front(LinkList*& L, LinkNode* node) {//L为头节点,node为新节点(子节点) if (!L || !node) return false;//防止链表为空 node->next = L->next;//将头节点指向的下一个节点的地址赋值给新节点 L->next = node; //将头节点指针指向新节点的地址 return true; } //遍历链表 void LinkPrint(LinkList*& L) { LinkNode* p = NULL; if (!L) { cout << "链表为空." << endl; return; } p = L->next; while (p) { cout << p->data << "\t"; p = p->next; } printf("\n"); } //尾插法 bool ListInsert_back(LinkList*& L, LinkNode* node) { LinkNode* last = NULL; if (!L || !node) return false;//判断是否为空 last = L;//指向头链表,将头链表的地址赋给last指针 //通过循环找到最后一个(节点)链表,即指针域存储为NULL的链表 while (last->next) last = last->next;//如果链表中next指针不为空,那么就指向下一个链表的地址 node->next = NULL;//将新节点的指针域设置为空 last->next = node;//将原链表中最后一个节点的指针指向新链表的地址 return true; } //任意位置插入 bool LinkInsert(LinkList*& L, int i, int& e) { //在单链表L中,在第i个位置插入元素e if (!L) return false; //判断是否为空 int j = 0; LinkList* p, * s; p = L; //指针p指向头节点 //找出要插入节点位置的前一个结点 while (p && j < i - 1) {//查找位置为i-1的节点,p指向该节点 p = p->next; j++; } if (!p || j > i - 1) {//判断p是否为空或者i值是否合法 return false; } s = new LinkNode;//生成新节点 s->data = e;//把插入的元素值赋值给新结点的数据域 s->next = p->next;//将新节点指针指向原i节点的地址 p->next = s;//将原(i-1)节点指针指向新节点地址 return true; } //单链表的取值 bool Link_GetElem(LinkList* &L,int i,int &e) { //在带头结点的单链表L中查找第i个元素(i为查找的元素位置) //用e记录L中第i个数据元素的值(e为被查找的元素值) int index; LinkList* p; if (!L || !L->next) return false; //判断是否为空 p = L->next;//p指向第一个节点 index = 1; //计数器,记录当前为哪一个节点(链表) while (p && index<i) {//链表依次向后扫描,直到指针p指向所指i个元素或者p为空 p = p->next; //p指向下一个节点(下一个链表的地址) index++; //每循环一次index加1 } if (!p || index > i) { return false; //要查询的元素个数i不合法,i>n或i<=0 } e = p->data;//将被查找节点的元素赋值给e return true; } //单链表查找元素(查询) bool Link_FindElem(LinkList* L, int e, int &index) {//按值查找 //在带头结点的单链表L中查找值为e的元素 LinkList* p; p = L->next; //指针p指向第一个节点 index = 1; //计数器 if (!L || !L->next) { index = -1; return false; }//判断是否为空 while (p && p->data != e) { //判断该节点元素值是否与要查找元素值相等 p = p->next; index++; //该节点位置 } if (!p) { index = -1; return false;//查无此值 } return true; } //单链表中元素的删除 bool LinkDelete(LinkList*& L, int i) {//i为要删除节点的位置 LinkList* p,*q; int index = 0; p = L;//将指针p指向头节点(链表) if (!L || !L->next) { return false; }//判断是否为空 //判断p指针是否为空 要删除节点位置i是否合法 while ((p->next) && (index < i - 1)) {//循环查找i节点 p = p->next; index++; } if (!p->next || (index > i - 1)) {//当i>n或者i<1时,删除位置不合理 return false; } q = p->next; //临时保存被删除节点的地址以备释放空间 p->next = q->next; //将(被删除节点)的前节点的指针指向(被删除节点)的后节点的地址 delete q; //释放被删除节点的空间 return true; } //单链表的销毁 void LinkDestroy(LinkList*& L) { //定义临时节点p指向头节点 LinkList* p = L; //将指针p指向头节点(链表) cout << "销毁链表" << endl; while (p) { L = L->next;//L指向下一个节点 delete p; //删除当前节点 p = L; //p移向下一个节点 } } int main(void) { LinkList* L = NULL; //定义一个链表指针,值置为空 LinkList* s = NULL; //1.初始化链表 InitList(L); //------------------------------------------------------------------------------- //2.前插法 int n; cout << "前插法创建单链表" << endl; cout << "请输入元素个数:"; cin >> n; cout << "\n请依次输入n个元素:"; while (n-- > 0) { s = new LinkNode; //生成新节点 cin >> s->data; ListInsert_front(L,s); } //打印链表 LinkPrint(L); cout << "-------------------" << endl; //------------------------------------------------------------------------------- //3.尾插法 cout << "尾插法创建单链表" << endl; cout << "请输入元素个数:"; cin >> n; cout << "\n请依次输入n个元素:"; while (n > 0) { s = new LinkNode; //生成新节点 cin >> s->data; ListInsert_back(L, s); n--; } //打印链表 LinkPrint(L); //------------------------------------------------------------------------------- //4.任意位置插入元素 int o; cout << "请问你要插几个元素:"; cin >> o; for (int r = 0; r < o; r++) { int i, x; cout << "请输入插入的位置和元素(用空格隔开):"; cin >> i; cin >> x; if (LinkInsert(L, i, x)) { cout << "插入成功!\n\n"; } else { cout << "插入失败!\n\n"; } //打印链表 LinkPrint(L); } //------------------------------------------------------------------------------- //5.获取链表中指定位置的元素值 int value = 0; int i = 0; cout << "你要获取哪个位置的元素?" << endl; cin >> i; if (Link_GetElem(L, i, value)) { cout << "获取成功! 值为:" << value << endl; } else { cout << "获取失败!" << endl; } //------------------------------------------------------------------------------- //6.查询链表中的元素 int index = 0; int e; cout << "输入你要查询的元素值:"; cin >> e; if (Link_FindElem(L, e, index)) { cout << "查询成功! 值为:" << e << endl; cout << "该值位置为" << index << endl; } else { cout << "查询失败!" << endl; } //------------------------------------------------------------------------------- //7.单链表中元素的删除 int w = 0; cout << "输入你要删除的元素位置:"; cin >> w; if (LinkDelete(L, w)) { cout << "删除成功!" << endl; } else { cout << "删除失败!" << endl; } //打印链表 LinkPrint(L); //------------------------------------------------------------------------------- //8.销毁链表 LinkDestroy(L); system("pause"); return 0; }
最新回复(0)