单链表
//带头结点
#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_); }