今天总结单链表的实现.
什么是链表?
就是采去链式存储结构的线性表,所谓链式存储就好比火车的车厢一样,一节一节的连接起来,成为一个线性表。这种方式采用动态存储分配方式,即程序在运行时根据实际需要申请内存空间,不需要时将内存空间释放掉。
链表用一组任意的存储单元存放线性表中的各个元素,这组存储单元可以是连续的,也可以是不连续的。
什么是单链表?
单链表简单理解就是单向的,就像火车一样。如果将火车头与火车为连接在一块,就构成了循环链表。
链表的结构:链表采用节点结构,这个节点分为两部分,一部分存储数据,一部分用来存储下一节点的地址,通过此地址就可以将各节点连接在一块。就好比火车车厢之间的连接,车厢用来存储货物,而车厢尾部有个挂钩之类的装置,用来连接两节车厢。
看一张形象的图,帮助理解.
具体实现:
<span style="font-family:Courier New;font-size:14px;">//链表节点 struct Node { T data; struct Node<T> *next; };</span>
<span style="font-family:Courier New;font-size:14px;">//链表类 template <class T> class LinkList { private: Node<T> *front; //头指针 public: LinkList() { //无参构造函数 空链表 front = new Node<T>; front->next = NULL; } LinkList(T a[],int n); //使用含有n个元素的数组a初始化链表 ~LinkList(); //析构函数 void PrintLinkList(); //遍历链表中的元素 int GetLength(); //获取链表长度 void Insert(int i,T x); //插入 Node<T> *Get(int i); //获取第i个元素的地址 T Delete(int i); //删除 并返回删除的元素 int Locate(T x); //值为x的元素所在的位置 }; </span><span style="font-family:Courier New;font-size:14px;">//采用头插法 初始化链表 template <class T> LinkList<T>::LinkList(T a[],int n) { front = new Node<T>; front->next = NULL; for(int i=n-1;i>=0;i--) { Node<T> *s = new Node<T>; s->data = a[i]; s->next = front->next; front->next = s; } }</span>
<span style="font-family:Courier New;font-size:14px;">//析构函数 释放结点 template <class T> LinkList<T>::~LinkList() { Node<T> *p = front; while(p) { front = p; p = p->next; delete front; //释放节点 } }</span>
<span style="font-family:Courier New;font-size:14px;">//获取链表的长度 template <class T> int LinkList<T>::GetLength() { int count = 0; Node<T> *p = front->next; //得到第一个节点 while(p!=NULL) { p=p->next; count++; } return count; } //循环遍历链表中的元素 template <class T> void LinkList<T>::PrintLinkList() { Node<T> *p = front->next; for(int i=0;i<GetLength();i++) { cout<<p->data<<" "; p=p->next; } cout<<endl; }</span>
<span style="font-family:Courier New;font-size:14px;">/* 返回指定位置的节点地址 思路: 1.获取工作指针p和计数器j,p指向第一个结点,j-1 2.循环遍历,直到p为空或j==i 3.返回p */ template <class T> Node<T> * LinkList<T>::Get(int i) { Node<T> *p = front->next; int j = 1; while(p&&j!=i) { p = p->next; j++; } return p; }</span>
<span style="font-family:Courier New;font-size:14px;">/**插入某元素到指定位置 思路: 1.初始化工作指针p,使其指向插入位置的前一个结点 2.新建一个结点,存储待插元素 3.将前一节点指向新建节点,并且将新建节点指向后续节点 */ template <class T> void LinkList<T>::Insert(int i,T x) { Node<T> *p = front; if(i!=1) p = Get(i-1); //获取要插入节点的前一个节点 if(p) { Node<T> *s = new Node<T>; //新建节点 s->data = x; //存储x s->next = p->next; p->next = s; }else { throw "插入位置错误"; } }</span>
<span style="font-family:Courier New;font-size:14px;">//删除指定位置的元素 与插入类似 template <class T> T LinkList<T>::Delete(int i) { Node<T> *p = front; if(i!=1) p = Get(i-1); if(p) { Node<T> *q = p->next; p->next = q->next; T x = q->data; delete q; return x; } return 0; } template <class T> int LinkList<T>::Locate(T x) { Node<T> *p = front->next; //第一个节点 int j = 1; while(p) { if(p->data==x) return j; p = p->next; j++; } return -1; //未找到 } int main() { int a[6] = {1,3,5,6,7,9}; LinkList<int> list(a,6); cout<<"单链表长度为:"<<list.GetLength()<<endl; cout<<"遍历单链表:"<<endl; list.PrintLinkList(); cout<<"在第三个位置插入12"<<endl; list.Insert(3,12); list.PrintLinkList(); cout<<"删除位置4的元素"<<endl; list.Delete(4); list.PrintLinkList(); cout<<"获取元素为6的位置"<<endl; cout<<list.Locate(6)<<endl; return 0; } </span>
结果:
时间: 2024-10-13 14:12:14