数据结构-链表
单链表中的每个结点不仅包含值,还包含链接到下一个结点的引用字段。通过这种方式,单链表将所有结点按顺序组织起来。与数组相比,查找索引需要从头开始遍历性能糟糕,但是插入删除元素则有优势。
C++实现单向链表加深理解
#include <iostream>
#include <set>
#include <unordered_set>
#include <vector>
#include <algorithm>
struct ListNode {
int val;
ListNode* next;
ListNode(int x) :val(x), next(NULL){}
};
class MyList {
public:
MyList();
~MyList();
/*创建*/
ListNode* CreatNewList(int val);
/*增*/
void addNewNodeBack(ListNode* Head, int val);
ListNode* addNewNodeFront(ListNode* Head, int val);
void InsertNewNodeIntoList(ListNode* Head, int locate, int val);
/*删*/
void DeleteList(ListNode* Head);
ListNode* DeleteNode(ListNode* Head, int locate);
/*查*/
int CheckNodeData(ListNode* Head, int locate);
/*改*/
void ChangeNodeData(ListNode* Head, int locate, int val);
/*翻转链表*/
ListNode* MyListReverse(ListNode* Head);
/*链表排序(从小到大)*/
ListNode* MyListSort(ListNode* Head);
/*移除重复节点*/
ListNode* MyListRemoveDuplicateNodes(ListNode* Head);
public:
void ShowListValue(ListNode* Head);
private:
};
MyList::MyList() {
}
MyList::~MyList() {
}
ListNode* MyList::CreatNewList(int val) {
ListNode* NewNode = new ListNode(val);
return NewNode;
}
void MyList::DeleteList(ListNode* Head) {
ListNode* node;
while (Head->next != NULL) {
node = Head->next;
delete Head;
Head = node;
}
delete Head;
}
void MyList::addNewNodeBack(ListNode* Head,int val) {
ListNode* NewNode = new ListNode(val);
while (Head->next != NULL) {
Head = Head->next;
}
Head->next = NewNode;
}
ListNode* MyList::addNewNodeFront(ListNode* Head, int val) {
ListNode* NewHead = new ListNode(val);
NewHead->next = Head;
return NewHead;
}
void MyList::InsertNewNodeIntoList(ListNode* Head, int locate, int val) {
int offset = 0;
while (offset != locate-1 && Head->next != NULL) {
offset++;
Head = Head->next;
}
if (offset == locate-1) {
ListNode* temp = Head->next;
ListNode* NewNode = new ListNode(val);
Head->next = NewNode;
NewNode->next = temp;
}
else {
std::cout << "locate over the list" << std::endl;
}
}
ListNode* MyList::DeleteNode(ListNode* Head, int locaet) {
int offset = 0;
ListNode* CopyHead = Head;
ListNode* temp = Head;
while (offset != locaet - 1 && Head->next != NULL) {
offset++;
temp = Head;
Head = Head->next;
}
if (offset == locaet - 1 && locaet != 1) {
temp->next = Head->next;
delete Head;
}
else if(locaet == 1){
ListNode* Node = Head->next;
delete Head;
return Node;
}
else {
std::cout << "locate over the list" << std::endl;
}
return CopyHead;
}
void MyList::ShowListValue(ListNode* Head) {
while (Head->next) {
std::cout << Head->val << "->";
Head = Head->next;
}
std::cout << Head->val << std::endl;
}
int MyList::CheckNodeData(ListNode* Head, int locate) {
int offset = 0;
int val = 0;
while (offset != locate - 1 && Head->next != NULL) {
offset++;
Head = Head->next;
}
if (offset == locate - 1) {
val = Head->val;
}
else {
std::cout << "locate over the list" << std::endl;
}
return val;
}
void MyList::ChangeNodeData(ListNode* Head, int locate, int val) {
int offset = 0;
while (offset != locate - 1 && Head->next != NULL) {
offset++;
Head = Head->next;
}
if (offset == locate - 1) {
Head->val = val;
}
else {
std::cout << "locate over the list" << std::endl;
}
}
ListNode* MyList::MyListReverse(ListNode* Head) {
if (Head == NULL) return NULL;
ListNode* NewEnd = new ListNode(Head->val);
NewEnd->next = NULL;
ListNode* CopyNewNode = NewEnd;
while (Head->next) {
Head = Head->next;
ListNode* NewNode = new ListNode(Head->val);
NewNode->next = CopyNewNode;
CopyNewNode = NewNode;
}
DeleteList(Head);
return CopyNewNode;
}
ListNode* MyList::MyListSort(ListNode* Head) {
if (Head == NULL) return NULL;
std::vector<int> box;
ListNode* copyhead1 = Head;
ListNode* copyhead2 = Head;
int locate = 0;
box.push_back(Head->val);
while (Head->next) {
Head = Head->next;
box.push_back(Head->val);
}
sort(box.begin(), box.end());
while (copyhead1->next) {
copyhead1->val = box[locate];
locate++;
copyhead1 = copyhead1->next;
}
copyhead1->val = box[locate];
return copyhead2;
}
ListNode* MyList::MyListRemoveDuplicateNodes(ListNode* Head) {
std::unordered_set<int> box;
ListNode* cur = Head;
while (cur && cur->next) {
box.insert(cur->val);
if (box.count(cur->next->val)) {
ListNode* DeleteNode = cur->next;
cur->next = cur->next->next;
delete DeleteNode;
}
else {
cur = cur->next;
}
}
return Head;
}
int main()
{
MyList M;
ListNode* Head;
Head = M.CreatNewList(1);
for (int i = 2; i < 11; ++i) {
M.addNewNodeBack(Head, i);
}
M.ShowListValue(Head);
ListNode* NewHead1 = M.MyListReverse(Head);
M.ShowListValue(NewHead1);
M.MyListSort(NewHead1);
M.ShowListValue(NewHead1);
///////////////
M.InsertNewNodeIntoList(NewHead1, 4, 4);
M.InsertNewNodeIntoList(NewHead1, 5, 5);
M.InsertNewNodeIntoList(NewHead1, 6, 6);
M.InsertNewNodeIntoList(NewHead1, 6, 9);
M.ShowListValue(NewHead1);
M.MyListRemoveDuplicateNodes(NewHead1);
M.ShowListValue(NewHead1);
///////////////
M.DeleteList(NewHead1);
return 0;
}
STL标准模板库的单向链表-Forword_list
#include <iostream>
#include <forward_list>
#include <algorithm>
#include <time.h>
using namespace std;
void showlist(forward_list<string>& ForwardList) {
for (string s : ForwardList) {
cout << s << "->";
}
cout << "NULL" << endl;
}
int main()
{
forward_list<string> ForwardList;
int starttime = 0;
int endtime = 0;
starttime = clock();
for (int i = 0; i < 500000; ++i) { //头插50万个“abc”
ForwardList.push_front("abc");
}
endtime = clock();
cout << "push from front time:" << endtime - starttime << endl;
starttime = clock();
for (int i = 0; i < 500000; ++i) {//删50万个“abc”
ForwardList.pop_front();
}
endtime = clock();
cout << "delete from front time:" << endtime - starttime << endl;
for (int i = 0; i < 500000; ++i) { //再头插50万个“abc”
ForwardList.push_front("abc");
}
starttime = clock();
ForwardList.clear();
endtime = clock();
cout << "delete from clear() time:" << endtime - starttime << endl;
/**********************************************/
ForwardList.emplace_front("def");
ForwardList.emplace_front("abc");
ForwardList.emplace_after(ForwardList.begin(), "ghi");//第一个参数是迭代器,支持在链表任意位置插入元素的,这里插入begin()的下一个位置
showlist(ForwardList);
ForwardList.erase_after(ForwardList.begin());//删除begin()的下一个位置的节点
showlist(ForwardList);
ForwardList.emplace_front("aaa");//同push_front
showlist(ForwardList);
ForwardList.remove("aaa");//删除链表中的指定的元素,不管在什么位置,有多少个
showlist(ForwardList);
ForwardList.reverse();//库里的反转链表
showlist(ForwardList);
return 0;
}
输出:
push from front time:1176
delete from front time:416
delete from clear() time:325
abc->ghi->def->NULL
abc->def->NULL
aaa->abc->def->NULL
abc->def->NULL
def->abc->NULL
还有很多api,需要用到时参考www.cplusplus.com
STL标准模板库的双向循环链表-List
#include <iostream>
#include <list>
#include <algorithm>
#include <time.h>
using namespace std;
void showlist(list<int>& List) {
for (int i : List) {
cout << i << "->";
}
cout <<"NULL"<< endl;
}
int main()
{
list<int> List;
clock_t timestart = 0;
clock_t timeend = 0;
timestart = clock();
for (int i = 0; i < 1000000; i++) {
List.push_back(i);//在链表尾添加元素
}
timeend = clock();
cout << "insert from back 1000000 time:" << timeend - timestart << endl;
timestart = clock();
for (int i = 0; i < 1000000; i++) {
List.pop_back();//从表尾开始删除元素
}
timeend = clock();
cout << "delete from back 1000000 time:" << timeend - timestart << endl;
timestart = clock();
for (int i = 0; i < 1000000; i++) {
List.push_front(i);//从表头开始添加元素
}
timeend = clock();
cout << "insert from front 1000000 time:" << timeend - timestart << endl;
timestart = clock();
for (int i = 0; i < 1000000; i++) {
List.pop_front();//从表头开始删除元素
}
timeend = clock();
cout << "delete from front 1000000 time:" << timeend - timestart << endl;
/***************************************************************************/
for (int i = 1; i <= 10; i++) {
List.emplace_back(i);//效果同push_back
}
showlist(List);
cout << "List First data is:" << List.front() << endl;
cout << "List Last data is:" << List.back() << endl;
List.pop_back();//删除最后一个节点
showlist(List);
List.pop_front();//删除第一个节点
showlist(List);
List.erase(List.begin(), ++++List.begin());//删除指定位置的节点用迭代器指示,也可以定个区间,这里贪方便就这样写了
showlist(List);
return 0;
}
输出:
insert from back 1000000 time:678
delete from back 1000000 time:374
insert from front 1000000 time:658
delete from front 1000000 time:345
1->2->3->4->5->6->7->8->9->10->NULL
List First data is:1
List Last data is:10
1->2->3->4->5->6->7->8->9->NULL
2->3->4->5->6->7->8->9->NULL
4->5->6->7->8->9->NULL
用库还是很难体现出双向循环列表的底层结构,参考www.cplusplus.com