链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。
其中存储数据元素信息的域称作数据域(设域名为data),存储直接后继存储位置的域称为指针域(设域名为next)。指针域中存储的信息又称做指针或链。
由分别表示,,…,的N 个结点依次相链构成的链表,称为线性表的链式存储表示,由于此类链表的每个结点中只包含一个指针域,故又称单链表或线性链表。
linkedlist.h ?//头文件,定义节点和链表信息及声明创建、插入、删除等基本函数
/*链表的实现,实现创建、插入、删除等操作*/ #include <string> using namespace std; struct StuInfo { int id; //学号 string name; //姓名 }; struct Node { StuInfo info; Node *next; Node(){} Node(StuInfo x){ info = x; next = NULL; } }; class LinkedList { public: LinkedList(); //构造函数 ~LinkedList(); //析构函数 void insert(StuInfo info, int pos); void remove(int id); //根据学生学号进行删除 int find(int id); //根据学号进行查找,返回节点位置 int getLength(); //获得链表长度 void print(); //打印链表信息 private: Node *head; int length; };
下面继续编写对应的源文件,linkedlist.cpp ?//实现具体函数内容
#include <iostream> #include "linkedlist.h" using namespace std; //构造函数 LinkedList::LinkedList() { head = NULL; length = 0; } //析构函数 LinkedList::~LinkedList() { Node* temp; for (int i = 0; i < length; i++) { temp = head; head = head->next; delete temp; } } void LinkedList::insert(StuInfo info, int pos) { if (pos < 0) { cout << "节点位置必须是正整数" << endl; } int index = 1; Node *temp = head; Node *node = new Node(info); if (pos == 0) { node->next = temp; head = node; length++; return; } while (index < pos && temp != NULL) { temp = temp->next; index++; } if (temp == NULL) { cout << "插入失败,位置序号超过链表长度" << endl; return; } node->next = temp->next; temp->next = node; length++; return; } void LinkedList::remove(int id) { int pos = find(id); if (pos == -1) { cout << "链表中没有该学号,无法删除对应信息" << endl; return; } if (pos == 0) { head = head->next; length--; return; } int index = 1; Node *temp = head; while (index < pos) { temp = temp->next; } temp->next = temp->next->next; length--; return; } int LinkedList::find(int id) { Node *temp = head; int index = 0; while (temp != NULL) { if (temp->info.id == id) { return index; } temp = temp->next; index++; } return -1; } int LinkedList::getLength() { return length; } void LinkedList::print() { if (head == NULL) { cout << "链表为空,没有信息" << endl; return; } Node *temp = head; while (temp != NULL) { cout << temp->info.id << "," << temp->info.name << endl; temp = temp->next; } cout << endl; return; }
,编写测试用的main函数
#include <iostream> #include <string> #include "linkedlist.h" using namespace std; int main() { LinkedList head; StuInfo info1, info2, info3, info4, info5; info1.id = 1001, info1.name = "张三", info2.id = 1002, info2.name = "莉丝", info3.id = 1003, info3.name = "李武", info4.id = 1004, info4.name = "六南", info5.id = 1005, info5.name = "琪琪"; //测试插入数据 cout << "测试插入:" << endl; head.insert(info1, 0); head.print(); head.insert(info2, 1); head.print(); head.insert(info3, 4); head.print(); head.insert(info4, 0); head.print(); head.insert(info5, 2); head.print(); //测试删除数据 cout << "测试删除:" << endl; cout << "链表长度为:" << head.getLength() << endl; head.remove(1004); head.print(); cout << "链表长度为:" << head.getLength() << endl; head.remove(1004); head.print(); return 0; }