#include<iostream>
using namespace std;
//链表的节点 节点里应包含节点要保存的数据和下一个节点的指针
struct node{
int value;
node *next;
// 节点的两个构造函数 没有数据且有指针情况会报错
node(int v,node* n = NULL):next(n),value(v){}
node():next(NULL){}
};
//链表类(头结点的位置为-1 链表是0~n-1 尾节点是n-1)
class list{
//私有成员应该包含 头尾节点和链表的长度 不能被用户访问
private:
node *head;
node *tail;
int len;
// 第n个节点的前驱(前一个节点) public函数内部使用函数 所以设为私有
node* _advance(const int n);
public:
//构造函数
list();
//析构函数
~list();
//获取链表长度
int getLen();
//获取头节点的指针
node* getHead();
//获取尾节点的指针
node* getTail();
//获取节点cur的前驱
node* priorNode(node *cur);
//获取index位置的节点指针
node* find_index(const int index);
//在index位置插入值为value的节点
void insert_list(const int index,const int value);
//删除index位置的节点
void remove_index(const int index);
//修改index位置的节点的数据
void update(const int index,const int value);
//寻找数据为value的节点 找到返回指针 没有找到则返回NULL
node* find_value(const int value);
//尾插入
void insert_tail(const int value);
//头插入
void insert_head(const int value);
//打印链表
void printList();
//清空链表 保存头尾节点
void deleteList();
//反转链表
void reverse_list();
//从小到大排序
void sort_list();
};
list::list()
{
head = new node();
tail = head;
len = 0;
}
list::~list()
{
deleteList();
delete head;
head = NULL;
}
node* list::_advance(const int n)
{
if(n < -1 || n > len)return NULL;
node *cur = head;
int i = 0;
while(i<n)
cur = cur->next,
++i;
return cur;
}
node* list::priorNode(node *cur)
{
node* lhs = head;
while(lhs->next && lhs->next->value != cur->value)
{
lhs = lhs->next;
}
return lhs->next;
}
int list::getLen()
{
return len;
}
node* list::getHead()
{
return head;
}
node* list::getTail()
{
return tail;
}
node* list::find_index(const int index)
{
if(index < 0 || index >= len)return NULL;
return (_advance(index)->next);
}
// 插入时需注意的几点
//1. 链表为空时,头插入完后 尾节点tail向后移一位
//2. 尾插入完以后 尾节点tail向后移一位
void list::insert_list(const int index,const int value)
{
if(index<0 || index>len)return;
node* before = _advance(index);
node* newNode = new node(value,before->next);
before->next = newNode;
if(before == tail)tail = newNode;//链表为空时 头插入也可以看做是一般的尾插入
len++;
}
//删除尾节点时 要将尾节点向前移一位
void list::remove_index(const int index)
{
if(index<0 || index>=len ||len == 0)return;
node* cur = _advance(index);
node* lhs = cur->next;
cur->next = cur->next->next;
if(lhs == tail)tail = cur;//判断删除的是不是尾节点
delete lhs;
lhs = NULL;
len--;
}
void list::update(const int index,const int value)
{
if(index<0 || index >= len)return;
_advance(index)->next->value = value;
}
node* list::find_value(const int value)
{
node* lhs = head->next;
while(lhs)
{
if(lhs->value == value)return lhs;
lhs = lhs->next;
}
return lhs;
}
void list::insert_tail(const int value)
{
node* newNode = new node(value);
tail->next = newNode;
tail = newNode;
len++;
}
//头插入 链表为空插入一个元素时 尾节点要后移一位
void list::insert_head(const int value)
{
node* newNode = new node(value,head->next);
head->next = newNode;
len++;
if(len == 1)tail = newNode;
}
void list::printList()
{
node* cur = head->next;
while(cur!=tail)
{
cout<<cur->value<<" ";
cur = cur->next;
}
cout<<cur->value<<endl;
}
void list::deleteList()
{
node* cur = head->next;
node* rhs;
while(cur)
{
rhs = cur->next;
delete cur;
cur = rhs;
}
tail = head;
len = 0;
}
//链表翻转
//当链表长度为0或者1时 结果与原链表一样 直接return
//当链表长度大于等于2时
//1.先将头结点和下一个节点与其他节点分开 并将头结点的下一个节点赋为尾节点
//2.将头结点和下一个节点作为一个新链表
//3.其他节点按原先链表顺序分别对新链表作头插入即可
void list::reverse_list()
{
if(len == 0 || len == 1)return;
// 先从第二个节点开始
node* cur = head->next->next;
node* rhs;
// 将头结点和下一个节点(也就是尾节点)作为一个新链表
// 并将尾节点的next赋值为NULL 如此把原先链表一分为二
tail = head->next;
tail->next = NULL;
// 将原链表其余的节点一个一个进行头插入
while(cur)
{
// 将要插入的节点的下一个节点的指针保存下来
// 为什么要保存 为什么不直接next获取呢
// 因为要插入的节点要插入新链表中
// 插入后它的next访问不到原先的下一个节点
// 如果不保存 我们没有办法再访问原先的下一个节点
rhs = cur->next;
// 接下来的两步操作即为插入操作
cur->next = head->next;
head->next = cur;
// 再插入下一个节点 直到为空
cur = rhs;
}
}
// 反转是不断进行头插入
// 而排序是有条件的进行插入 原理差不多 但还是有些许差别 多一步 就是要找插入的位置
void list::sort_list()
{
if(len == 0 || len == 1)return;
node* cur = head->next->next;
node* rhs,lhs;
tail = head->next;
tail->next = NULL;
node* sql;
while(cur)
{
rhs = head;
sql = cur->next;
// 每次插入都要从新链表的头结点一直到为NULL进行比较
// 如果要插入的节点大于新链表的节点 就后移一位比较
// 直到碰到小于等于新链表的节点或者新链表全部比较完(也就是全部比它小)就插入 (直接插入排序思想)
// 如果插入的位置为新链表的最后一位 尾节点要后移一位
while(rhs->next && cur->value > rhs->next->value)rhs = rhs->next;
cur->next = rhs->next;
rhs->next = cur;
if(rhs == tail)tail = cur;
cur = sql;
}
}
using namespace std;
//链表的节点 节点里应包含节点要保存的数据和下一个节点的指针
struct node{
int value;
node *next;
// 节点的两个构造函数 没有数据且有指针情况会报错
node(int v,node* n = NULL):next(n),value(v){}
node():next(NULL){}
};
//链表类(头结点的位置为-1 链表是0~n-1 尾节点是n-1)
class list{
//私有成员应该包含 头尾节点和链表的长度 不能被用户访问
private:
node *head;
node *tail;
int len;
// 第n个节点的前驱(前一个节点) public函数内部使用函数 所以设为私有
node* _advance(const int n);
public:
//构造函数
list();
//析构函数
~list();
//获取链表长度
int getLen();
//获取头节点的指针
node* getHead();
//获取尾节点的指针
node* getTail();
//获取节点cur的前驱
node* priorNode(node *cur);
//获取index位置的节点指针
node* find_index(const int index);
//在index位置插入值为value的节点
void insert_list(const int index,const int value);
//删除index位置的节点
void remove_index(const int index);
//修改index位置的节点的数据
void update(const int index,const int value);
//寻找数据为value的节点 找到返回指针 没有找到则返回NULL
node* find_value(const int value);
//尾插入
void insert_tail(const int value);
//头插入
void insert_head(const int value);
//打印链表
void printList();
//清空链表 保存头尾节点
void deleteList();
//反转链表
void reverse_list();
//从小到大排序
void sort_list();
};
list::list()
{
head = new node();
tail = head;
len = 0;
}
list::~list()
{
deleteList();
delete head;
head = NULL;
}
node* list::_advance(const int n)
{
if(n < -1 || n > len)return NULL;
node *cur = head;
int i = 0;
while(i<n)
cur = cur->next,
++i;
return cur;
}
node* list::priorNode(node *cur)
{
node* lhs = head;
while(lhs->next && lhs->next->value != cur->value)
{
lhs = lhs->next;
}
return lhs->next;
}
int list::getLen()
{
return len;
}
node* list::getHead()
{
return head;
}
node* list::getTail()
{
return tail;
}
node* list::find_index(const int index)
{
if(index < 0 || index >= len)return NULL;
return (_advance(index)->next);
}
// 插入时需注意的几点
//1. 链表为空时,头插入完后 尾节点tail向后移一位
//2. 尾插入完以后 尾节点tail向后移一位
void list::insert_list(const int index,const int value)
{
if(index<0 || index>len)return;
node* before = _advance(index);
node* newNode = new node(value,before->next);
before->next = newNode;
if(before == tail)tail = newNode;//链表为空时 头插入也可以看做是一般的尾插入
len++;
}
//删除尾节点时 要将尾节点向前移一位
void list::remove_index(const int index)
{
if(index<0 || index>=len ||len == 0)return;
node* cur = _advance(index);
node* lhs = cur->next;
cur->next = cur->next->next;
if(lhs == tail)tail = cur;//判断删除的是不是尾节点
delete lhs;
lhs = NULL;
len--;
}
void list::update(const int index,const int value)
{
if(index<0 || index >= len)return;
_advance(index)->next->value = value;
}
node* list::find_value(const int value)
{
node* lhs = head->next;
while(lhs)
{
if(lhs->value == value)return lhs;
lhs = lhs->next;
}
return lhs;
}
void list::insert_tail(const int value)
{
node* newNode = new node(value);
tail->next = newNode;
tail = newNode;
len++;
}
//头插入 链表为空插入一个元素时 尾节点要后移一位
void list::insert_head(const int value)
{
node* newNode = new node(value,head->next);
head->next = newNode;
len++;
if(len == 1)tail = newNode;
}
void list::printList()
{
node* cur = head->next;
while(cur!=tail)
{
cout<<cur->value<<" ";
cur = cur->next;
}
cout<<cur->value<<endl;
}
void list::deleteList()
{
node* cur = head->next;
node* rhs;
while(cur)
{
rhs = cur->next;
delete cur;
cur = rhs;
}
tail = head;
len = 0;
}
//链表翻转
//当链表长度为0或者1时 结果与原链表一样 直接return
//当链表长度大于等于2时
//1.先将头结点和下一个节点与其他节点分开 并将头结点的下一个节点赋为尾节点
//2.将头结点和下一个节点作为一个新链表
//3.其他节点按原先链表顺序分别对新链表作头插入即可
void list::reverse_list()
{
if(len == 0 || len == 1)return;
// 先从第二个节点开始
node* cur = head->next->next;
node* rhs;
// 将头结点和下一个节点(也就是尾节点)作为一个新链表
// 并将尾节点的next赋值为NULL 如此把原先链表一分为二
tail = head->next;
tail->next = NULL;
// 将原链表其余的节点一个一个进行头插入
while(cur)
{
// 将要插入的节点的下一个节点的指针保存下来
// 为什么要保存 为什么不直接next获取呢
// 因为要插入的节点要插入新链表中
// 插入后它的next访问不到原先的下一个节点
// 如果不保存 我们没有办法再访问原先的下一个节点
rhs = cur->next;
// 接下来的两步操作即为插入操作
cur->next = head->next;
head->next = cur;
// 再插入下一个节点 直到为空
cur = rhs;
}
}
// 反转是不断进行头插入
// 而排序是有条件的进行插入 原理差不多 但还是有些许差别 多一步 就是要找插入的位置
void list::sort_list()
{
if(len == 0 || len == 1)return;
node* cur = head->next->next;
node* rhs,lhs;
tail = head->next;
tail->next = NULL;
node* sql;
while(cur)
{
rhs = head;
sql = cur->next;
// 每次插入都要从新链表的头结点一直到为NULL进行比较
// 如果要插入的节点大于新链表的节点 就后移一位比较
// 直到碰到小于等于新链表的节点或者新链表全部比较完(也就是全部比它小)就插入 (直接插入排序思想)
// 如果插入的位置为新链表的最后一位 尾节点要后移一位
while(rhs->next && cur->value > rhs->next->value)rhs = rhs->next;
cur->next = rhs->next;
rhs->next = cur;
if(rhs == tail)tail = cur;
cur = sql;
}
}