#include
using namespace std;
typedef int TELemType;
const int N = 100010;
// 链表节点
struct node{
TELemType data;
node* next;
};
//初始化
node* init()
{
node* head = new node;
head->next = NULL;
return head;
}
// 查找值为x的结点的个数
int search(node* head, int x)
{
int count = 0;
node* p = head->next;
while(p){
if(p->data == x) count ++;
p = p->next;
}
return count;
}
// 在第k个结点后插入结点
void insert(node* head, int k, int x)
{
node* p = head;
for(int i = 0; i < k; i ++) p = p->next;
node* q = new node;
q->data = x;
q->next = p->next;
p->next = q;
}
// 删除第k个结点后面的结点
void remove(node* head, int k)
{
node* p = head;
// 分删除头结点和删除其他结点两种情况
if(k){
p = head->next;
head = p->next;
delete(p);
}
else{
for(int i = 0; i <= k; i ++) p = p->next;
node* q = p->next;
p->next = q->next;
delete(q);
}
}
// 删除值为x的结点
void del(node* head, int x)
{
node* p = head->next;
node* pre = head;
while(p){
if(p->data == x){
pre->next = p->next;
delete (p);
p = pre->next;
}
else{
pre = p;
p = p->next;
}
}
}
// 输出链表
void listprint(node* head)
{
node* p = head->next;
while(p){
cout<<p->data<<' ';
p = p->next;
}
}
#include
using namespace std;
const int N = 100010;
typedef int TELemType;
struct node{
TELemType val; // 数据域
int nex; // 指针域
}Node[N];
int head, idx;
// head是链首指针
// idx是当前可以使用的数组元素的下标
// 初始化
void init()
{
head = -1;
idx = 0;
}
/*
注意区分链首指针和头结点
头结点是第1个结点,但是下标不确定
链首指针初始值为-1,以后值为头结点下标
*/
/*
头结点一般放在第一个结点之前,数据域无意义
头结点用来统一首元结点(第一个数据域有意义的结点)和其他结点的操作
本模板的头结点不是常规意义的头结点,而是和首元结点是同一个结点
*/
// 插入头结点
void head_insert(int x)
{
Node[idx].val = x;
Node[idx].nex = head;
head = idx ++;
}
// 在第k个结点后面插入结点
void insert(int k, int x)
{
// 注意数组下标从0开始,第k个结点下标是k-1
k = k-1;
Node[idx].val = x;
Node[idx].nex = Node[k].nex;
Node[k].nex = idx ++;
}
// 删除第k个结点后面的结点
void remove(int k)
{
// 分删除头结点和删除其他结点两种情况
if(!k) head = Node[head].nex;
else Node[k-1].nex = Node[node[k-1].nex].nex;
}
// 删除值为x的结点(可能删除多个结点)
void del(int x)
{
// 判断是否删除头结点
if(Node[head].val == x) head = Node[head].nex;
// 遍历头结点之后的结点
for(int i = head; i != -1; i = Node[i].nex){
if(Node[i].nex != -1 && Node[Node[i].nex].val == x)
Node[i].nex = Node[Node[i].nex].nex;
}
}
// 查找值为x的结点的个数
int search(int x)
{
int count = 0;
for(int i = head; i != -1; i = Node[i].nex)
if(Node[i].val == x) count ++;
return count;
}
// 输出链表
void listprint()
{
for(int i = head; i != -1; i = Node[i].nex)
cout<<Node[i].val<<' ';
}
#include
using namespace std;
const int N = 100010;
typedef int TELemType;
struct node{
TELemType val; // 数据域
int pred; // 前驱指针
int succ; // 后继指针
}Node[N];
int idx; // idx是当前可以使用的数组元素的下标
// 初始化双链表(链首指针和链尾指针)
void init()
{
Node[1].pred = 0;
Node[0].succ = 1;
idx = 2;
}
// 在第k个结点右侧插入结点
void insert(int k, int x)
{
Node[idx].val = x;
Node[idx].pred = k;
Node[idx].succ = Node[k].succ;
Node[node[k].succ].pred = idx;
Node[k].succ = idx ++;
}
// 删除第k个结点
void remove(int k)
{
Node[node[k].pred].succ = Node[k].succ;
Node[node[k].succ].pred = Node[k].pred;
}
其实就是解开对结构数组的封装,这样写起来更简洁方便(但是略微难懂),比赛一般使用这种做法。
解开封装后数据域数组和指针域数组通过数组下标(相同)联系
/*
易错点:
1.忘记初始化链表
2.删除节点要分删除头节点和删除其他节点两种情况
3.注意数组下标从0开始,第k个节点下标是k-1
*/
#include
using namespace std;
const int N = 100010;
int head, val[N], nex[N], idx;
// val数组存放节点值,nex数组存放当前节点的下一个节点的地址
// head是链首指针,idx是当前可以使用的数组元素的下标值
// 数据和指针通过数组下标联系起来
// 初始化
void init()
{
head = -1;
idx = 0;
}
// 插入头节点
void head_insert(int x)
{
val[idx] = x;
nex[idx] = head;
head = idx ++;
}
//在第k个节点后面插入节点
void insert(int k, int x)
{
// 注意数组下标从0开始,第k个节点下标是k-1
k = k - 1
val[idx] = x;
nex[idx] = nex[k];
nex[k] = idx ++;
}
//删除第k个节点后面的节点
void remove(int k)
{
// 删除节点要分删除头节点和删除其他节点两种情况
if(!k) head = nex[head];
else nex[k-1] = nex[nex[k-1]];
}
// 删除值为x的结点(可能删除多个结点)
void del(int x)
{
// 判断删除不删除头结点
if(val[head] == x) head = nex[head];
// 遍历头结点之后的结点
for(int i = head; i != -1; i = nex[i]){
if(nex[i] != -1 && val[nex[i]] == x)
nex[i] = nex[nex[i]];
}
}
// 查找值为x的结点的个数
int search(int x)
{
int count = 0;
for(int i = head; i != -1; i = nex[i])
if(val[i] == x) count ++;
return count;
}
// 输出链表
void listprint()
{
for(int i = head; i != -1; i = nex[i])
cout<<val[i]<<' ';
}
/*
易错点:
1.忘记初始化链表
2.数组前两个元素分别被用作链首指针和链尾指针,所以第k个节点的下标是k+1
*/
#include
#include
using namespace std;
const int N = 100010;
int val[N], pred[N], succ[N], idx;
// val数组存放节点值,idx是当前可以使用的数组元素的下标值
// pred数组存放当前节点的前驱指针,succ数组存放当前节点的后继指针
// 数据和指针通过数组下标联系起来
// 初始化双链表
void init()
{
pred[1] = 0;
succ[0] = 1;
idx = 2;
}
// 在第k个节点右侧插入节点
void insert(int k, int x)
{
val[idx] = x;
pred[idx] = k;
succ[idx] = succ[k];
pred[succ[k]] = idx;
succ[k] = idx ++;
}
// 删除第k个节点
void remove(int k)
{
succ[pred[k]] = succ[k];
pred[succ[k]] = pred[k];
}
vector模拟单链表:
#include
using namespace std;
typedef int TELemType;
//const int N = 100010;
// 链表结点
struct node
{
TELemType val1;
TELemType val2;
// 如val1表示(图)边终点,val2表示边权
};
vector<node> sinlist;
/*
把sinlist换成数组即可实现邻接链表
即:vector adjlist[N]
*/
//初始化
sinlist.clear();
// 在链表末插入结点
void tail_insert(int x, int k)
{
sinlist.push_back(node(x, k)); // 调用结构体的构造函数
}
// 删除第pos个结点
void remove(int pos)
{
sinlist.erase(sinlist.begin()+pos, sinlist.begin()+pos+1);
}
vector模拟邻接链表
vecotr<typename> Arrayname[arraySize];
一维长度固定为arraySize,另一维变长,Arrayname[0]~Arrayname[arraySize-1]中的每一个都是一个vector容器
vector<vector<typename> >name
两个维度都是可变的
Python的list的实现方式正是数据结构vector(不是stl的vector)
Python list implementation
#include
using namespace std;
struct node{
void* data;
node* next;
};
class sinLink{
public:
sinLink();
~sinLink();
void insert(void* x, int pos);
void remove(int pos);
int search(void* x);
void listprint();
void del(void* x);
int getsize() const {return size;};
node* getfront() {return head;};
private:
node* head;
int size;
};
// 构造函数
sinLink::sinLink()
{
head = new node;
size = 0;
}
// 构析函数
sinLink::~sinLink()
{
if(head == NULL) return;
while(head)
{
node * pNext = head->next;
delete head;
head = pNext;
}
size = 0;
}
// 在pos位置后插入结点
void sinLink::insert(void* x, int pos)
{
node* p = head;
for(int i = 0; i < pos; i ++) p = p->next;
node* q = new node;
q->data = x;
q->next = p->next;
p->next = q;
size ++;
}
// 删除pos位置后的结点
void sinLink::remove(int pos)
{
node* p = head;
// 分删除头结点和删除其他结点两种情况
if(pos){
p = head->next;
head = p->next;
delete(p);
size --;
}
else{
for(int i = 0; i < pos; i ++) p = p->next;
node* q = p->next;
p->next = q->next;
delete(q);
size --;
}
}
// 删除值为x的结点
void sinLink::del(void* x)
{
node* p = head->next;
node* pre = head;
while(p){
if(p->data == x){
pre->next = p->next;
delete (p);
size --;
p = pre->next;
}
else{
pre = p;
p = p->next;
}
}
}
// 查找值为x的结点的个数
int sinLink::search(void* x)
{
int count = 0;
node* p = head->next;
while(p){
if(p->data == x) count ++;
p = p->next;
}
return count;
}
// 输出链表
void sinLink::listprint()
{
node* p = head->next;
while(p){
cout<<p->data<<' ';
p = p->next;
}
}
#include
using namespace std;
template <typename T> struct node{
void* data;
node* next;
};
template <typename T> class sinLink{
public:
sinLink();
~sinLink();
void insert(void* x, int pos);
void remove(int pos);
int search(void* x);
void listprint();
void del(void* x);
int getsize() const {return size;};
node* getfront() {return head;};
private:
node* head;
int size;
};
// 构造函数
template <typename T> sinLink::sinLink()
{
head = new node;
size = 0;
}
// 构析函数
template <typename T> sinLink::~sinLink()
{
if(head == NULL) return;
while(head)
{
node * pNext = head->next;
delete head;
head = pNext;
}
size = 0;
}
// 在pos位置后插入结点
template <typename T> void sinLink::insert(void* x, int pos)
{
node* p = head;
for(int i = 0; i < pos; i ++) p = p->next;
node* q = new node;
q->data = x;
q->next = p->next;
p->next = q;
size ++;
}
// 删除pos位置后的结点
template <typename T> void sinLink::remove(int pos)
{
node* p = head;
// 分删除头结点和删除其他结点两种情况
if(pos){
p = head->next;
head = p->next;
delete(p);
size --;
}
else{
for(int i = 0; i < pos; i ++) p = p->next;
node* q = p->next;
p->next = q->next;
delete(q);
size --;
}
}
// 删除值为x的结点
template <typename T> void sinLink::del(void* x)
{
node* p = head->next;
node* pre = head;
while(p){
if(p->data == x){
pre->next = p->next;
delete (p);
size --;
p = pre->next;
}
else{
pre = p;
p = p->next;
}
}
}
// 查找值为x的结点的个数
template <typename T> int sinLink::search(void* x)
{
int count = 0;
node* p = head->next;
while(p){
if(p->data == x) count ++;
p = p->next;
}
return count;
}
// 输出链表
template <typename T> void sinLink::listprint()
{
node* p = head->next;
while(p){
cout<<p->data<<' ';
p = p->next;
}
}