链表就是有n各结点链接形成一个表,所谓结点就是包含了本身的数据元素,和一个指示直接后继的存储位置,即结点包含两个部分(数据域 指针域)。但是链表的存取必须是从头指针开始进行的,头指针指向第一个结点的存储位置,用head 表示,但head只是指向了头结点,本身不是一个结点 ,而是一个指针。
定义结点的结构体:
struct Node{
int data;
Node* next;
}
下面给出一个链表的各种操作的代码进行解释说明:
#include <iostream>
using namespace std;
typedef int T;
class List{
struct Node{
T data;
Node* next;
Node(const T& d=T()):data(d),next(NULL){}
};
Node* head;
public:
List():head(NULL){}
~List(){
clear(); //逐个释放
}
void clear(){
Node* p = head->next;
delete head;
head = p;
}
//插入操作
void insert(const T& t){
Node* p = new Node(t);
p->next = head;
head = p;
}
//遍历
void travel(){
Node* p = head;
while(p!=NULL){
cout<<p->data<<endl;
p = p->next;
}
}
//链表的大小
int size(){
Node* p = head;
int cnt=0;
while(p!=NULL){
cnt++;
p = p->next;
}
return cnt;
}
//获取头结点元素值
T getHead(){
if(head==NULL)throw"no head";
return head->data;
}
//获取尾结点元素值
T getTail(){
if(head==NULL)throw"no tail";
Node* p = head;
while(p!=NULL){
p = p->next;
}
return p->data;
}
//判断是否为空
bool empty(){
return head==NULL;
}
//查找一个元素
int find(const T& t){
int pos=0;
Node* p = head;
while(p!=NULL){
if(p->data==t){
return pos;
}
p = p->next;
pos++;
}
return -1;
}
//修改
bool update(const T& o,const T& t){
int pos = find(o);
if(pos==-1){
return false;
}
Node* p = getpoint(pos); //获得到需要修改的指针
p->data = t;
return true;
}
//获得某个位置的指针
Node* getpoint(int pos){
Node* p = head;
for(int i=0;i<pos;i++)
p = p->next;
return p;
}
//删除元素
bool erase(const T& t){
int pos = find(t);
if(pos==-1){
cout<<"NO Node"<<endl;
}
if(pos==0){
Node* p = head->next;
delete head;
head = p;
}
else{
Node* pre = getpoint(pos-1);
pre->next = pre->next->next;
delete pre;
}
}
};
在链表之中还需要后插入
void insert_back(const T& t){
Node* p = new Node(t);
if(head == NULL){
head = p;
}
else{
getpoint(size()-1)->next = p;
}
}
栈和队列基本就是对应于单链表进行的操作,栈是先进后出的,而队列是先进现出
基于单链表的栈的一些基本操作:
class Stack{
List list; //包含上面链表的类
public:
//向栈顶插入一个元素
void push(const T& t){
list.insert(t);
}
//出栈
void pop(){
list.erase(list.getHead);
}
//获得栈顶元素
int top(){
return list.getHead();
}
//判断栈是否为空
bool empty(){
return list.empty();
}
//栈的大小
int size(){
return list.size();
}
//清空这个栈
void clear(){
list.clear();
}
};
基于链表的队列的操作:
class Queue{
List list; //包含上面链表的类
public:
//向队列末插入一个元素
void push(const T& t){
list.insert_back(t);
}
//删除队首元素
void pop(){
list.erase(list.getHead);
}
//获得队首元素
int front(){
return list.getHead();
}
//获得队尾元素
int back(){
return list.getTail();
}
//判断队列是否为空
bool empty(){
return list.empty();
}
//队列的大小
int size(){
return list.size();
}
//清空这个队列
void clear(){
list.clear();
}
};
同时在C++STL中 提供了栈和队列的适配器具体的操作如下:
栈适配器:
s.pop() 删除栈顶元素
s.empty() 栈为空
s.push(item) 向栈顶插入元素
s.size() 栈的大小
s.top() 获取栈顶元素
队列适配器:
q.empty() 队列为空
q.pop() 删除队首元素
q.size() 队列大小
q.push(item) 向队尾插入元素
q.front() 获取队首元素
q.back() 获取队尾元素
q.top() 返回一个优先级高的元素 只适用于优先队列
这些操作在STL提供下是直接可以应用的 无需上面写大段的代码,只须使用前包含 <stack> <queue> 头文件即可。
链表的逆序输出:只给出链表的头结点,逆序输出整个链表。
c++代码简介:
#include <iostream>
#include <stack>
using namespace std;
struct linkNode{
int value;
linkNode* next;
};
//创建结点
linkNode* createNode(int value){
linkNode* pNode = new linkNode();
pNode->value = value;
pNode->next = NULL;
return pNode;
}
//打印链表
void printNode(linkNode* phead){
linkNode* pNode = phead;
if(pNode==NULL){
cout<<"list is null"<<endl;
}
while(pNode!=NULL){
cout<<pNode->value<<" ";
pNode = pNode->next;
}
cout<<endl;
}
//向链表的末端插入结点,并且保存好链表的结构,所以需要传递一个节点引用,所以形参是一个指向指针的指针
void addToTail(linkNode** phead,int value){
linkNode* pNew = new linkNode();
pNew->value = value;
pNew->next = NULL;
if(*phead==NULL){
*phead = pNew;
}else{
linkNode* pNode = *phead;
while(pNode->next!=NULL){
pNode = pNode->next;
}
pNode->next = pNew;
}
}
void printreverse(linkNode* phead){
linkNode* pNode = phead;
stack<linkNode*> nodes;
while(pNode!=NULL){
nodes.push(pNode);
pNode = pNode->next;
}
while(!nodes.empty()){
pNode = nodes.top();
cout<<pNode->value<<" ";
nodes.pop();
}
cout<<endl;
}
//递归调用
void print_revserse_order(linkNode* phead){
linkNode* pNode = phead;
if(pNode!=NULL){
if(pNode->next!=NULL){
print_revserse_order(pNode->next);
}
}
cout<<pNode->value<<" ";
}
int main()
{
linkNode* p_Node = createNode(1); //创建一个结点
printNode(p_Node);
addToTail(&p_Node,2); //添加一个结点
addToTail(&p_Node,3);
addToTail(&p_Node,4);
addToTail(&p_Node,5);
addToTail(&p_Node,6);
addToTail(&p_Node,7);
addToTail(&p_Node,8);
addToTail(&p_Node,9);
addToTail(&p_Node,0);
printreverse(p_Node); // 逆序打印
print_revserse_order(p_Node);
return 0;
}