单向链表
优点:插入或删除元素时很方便,使用灵活,存储空间利用率高。
缺点:存储密度小(<1),查找和修改需要遍历整个链表。
头文件
#include<iostream>
定义结点
template<class T>
class LNode
{
public:
T data;
LNode<T> * _next;
};
链表类
template<class T>
class LinkList
{
public:
LinkList();
~LinkList();
bool clear();
int length();
bool get(int pos, T&t);
bool insert(int pos, T t);
void printList();
private:
LNode<T>* head;
};
初始化一个头结点
template<class T>
LinkList<T>::LinkList()
{
// 初始化一个头结点
head = new LNode<T>;
head->data = NULL;
head->_next = nullptr;
}
清空链表
template<class T>
LinkList<T>::~LinkList()
{
clear();
}
template<class T>
bool LinkList<T>::clear()
{
LNode<T> *p = head;
while (head)
{
p = head;
head = head->_next;
delete p;
}
return true;
}
获取链表长度
template<class T>
int LinkList<T>::length() {
LNode<T>*p = head->_next; //不能直接用head循环
int len = 0;
while (p!=nullptr)
{
len++;
p = p->_next;
}
return len;
}
获取链表中指定位置元素
template<class T>
bool LinkList<T>::get(int pos, T&t) {
LNode<T>* p = head; //不能直接用head循环
int j = 0;
while (j<i&&p)
{
p = p->_next;
j++;
}
if (p == nullptr) return false;
t = p->data;
return true;
}
链表插入结点
template<class T>
bool LinkList<T>::insert(int pos, T t)
{
LNode<T>*p = head;
LNode<T>*s = nullptr;
int loc = 0;
if (pos>=length()) //尾部插入
{
s = new LNode<T>;
s->data = t;
s->_next = nullptr;
if (head->_next==nullptr)
{
head->_next = s;
s->_next = nullptr;
return true;
}
while (p->_next!=nullptr)
{
p = p->_next;
}
p->_next = s;
return true;
}
//中间任意位置插法
while (p&&loc<pos - 1)
{
p = p->_next;
loc++;
}
s = new LNode<T>;
s->data = t;
s->_next = p->_next;
p->_next = s;
return true;
}
遍历链表
template<class T>
void LinkList<T>::printList()
{
LNode<T> * p = head->_next;
while (p!=nullptr)
{
std::cout << p->data << " ";
p = p->_next;
}
}
小样
int main(int argvn, char**argv)
{
std::cout << "-----单链表-----" << std::endl;
LinkList<int> linkList;
//cin >> pnew->data;
linkList.insert(1, 4);
linkList.insert(0, 5);
linkList.insert(2, 12);
linkList.insert(3, 5);
linkList.insert(4, 3);
linkList.insert(5, 7);
std::cout << "length " << linkList.length() << std::endl;
std::cout << "\n";
linkList.printList();
linkList.clear();
system("pause");
return 0;
}
输出:
-----单链表-----
length 6
5 4 12 5 3 7
双向链表
单链表结点中只有一个指向其后继的指针,使得单链表只能从头结点依次顺序地向后遍历。要访问某个结点的前驱结点(插入,删除操作时),只能从头开始遍历,访问后继结点的时间复杂度为O(1),访问前驱结点的时间复杂度为O(n)。
为了克服单链表的上述缺点,引入了双链表,双链表结点中有两个指针prev和next,分别指向其前驱结点和后继结点。
头文件
#include<iostream>
定义结点
template<class T>
class DLNode {
public:
T data;
DLNode<T> * _prev;
DLNode<T> * _next;
};
链表类
template<class T>
class DLinkList
{
public:
DLinkList();
~DLinkList();
void add(T t);
int size();
void print();
void clear();
void remove(T index);
T find(int index);
private:
DLNode<T> * head;
DLNode<T>* tail;
int length;
};
初始化一个头结点和尾结点
template<class T>
DLinkList<T>::DLinkList()
{
head = new DLNode<T>;
tail = new DLNode<T>;
head->data = NULL;
head->_prev = nullptr;
tail->data = NULL;
tail->_next = nullptr;
head->_next = tail;
tail->_prev = head;
}
清空链表
template<class T>
void DLinkList<T>::clear()
{
if (length==0)
{
return;
}
DLNode<T> * p = head->_next;
while (p!=tail)
{
DLNode<T>* temp = p;
p = p->_next;
delete temp;
}
head->_next = tail;
tail->_prev = head;
length = 0;
}
添加元素
template<class T>
void DLinkList<T>::add(T t)
{
tail->data = t;
tail->_next = new DLNode<T>;
DLNode<T> *p = tail;
tail = tail->_next; // 将tail结点指针 指向 新的空结点
tail->_prev = p; //将tail结点前驱指针指向 之前所有数据
tail->_next = nullptr; //将tail结点后继指针置空
length++;
}
遍历链表
template<class T>
void DLinkList<T>::print()
{
if (length==0)
{
std::cout << "List is empty" << std::endl;
return;
}
DLNode<T> * temp = head->_next;
while (temp != tail)
{
std::cout << temp->data << " ";
temp = temp->_next;
}
std::cout << "\n";
}
移除结点
template<class T>
void DLinkList<T>::remove(T index)
{
if (length==0)
{
std::cout << "List is empty";
return;
}
DLNode<T> *p = head;
while (p->_next!=nullptr)
{
p = p->_next;
if (p->data==index)
{
DLNode<T> * temp = p->_prev;
temp->_next = p->_next;
p->_next->_prev = temp;
delete p;
length--;
return;
}
}
}
查找链表结点
template<class T>
T DLinkList<T>::find(int index)
{
if (length==0)
{
std::cout << "List is empty";
return NULL;
}
if (index>=length)
{
std::cout << "Out of bounds";
return NULL;
}
int i = 0;
DLNode<T> * p = head->_next;
while (p!=tail&& i++ != index)
{
p = p->_next;
}
return p->data;
}
获取链表长度
template<class T>
int DLinkList<T>::size()
{
return length;
}
小样
int main(int argn, char**argv)
{
DLinkList<int> dlinklist;
dlinklist.add(1);
dlinklist.add(2);
dlinklist.add(3);
dlinklist.remove(1);
std::cout<<"find "<<dlinklist.find(1)<<"\n";
dlinklist.print();
system("pause");
return 0;
}
输出:
find 3
2 3
请按任意键继续. . .