本文针对单链表,总结其相应的常用操作。主要是给出代码实现。
常量声明
common.h
#ifndef common_H
#define common_H
/* 函数结果状态码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//#define OVERFLOW -2
/* 类型定义 */
typedef int Status; // Status是函数的类型,其值是函数结果状态码
typedef int ElemType; // ElemType是数据类型
#endif
链表节点结构及常用操作接口声明
LinkedList.h
注:以下常用操作接口均为带头结点的实现
#ifndef LinkedList_H
#define LinkedList_H
#include "common.h"
#include <cstdlib>
/* 链表节点声明 */
struct ListNode
{
ElemType data;
ListNode* next;
ListNode() : data(0), next(NULL) {}
ListNode( ElemType x ) : data(x), next(NULL) {}
};
typedef ListNode* LinkedList; // LinkedList是指向类型ListNode的指针
LinkedList create_by_head( const ElemType* arr, int n ); // 头插法
LinkedList create_by_tail( const ElemType* arr, int n ); // 尾插法
Status destroy( LinkedList head ); // 销毁
Status destroy1( LinkedList head ); // 销毁 - 递归实现
Status print( LinkedList head ); // 枚举
Status print1( LinkedList head ); // 枚举 - 递归实现 - 调用函数时参数为head->next,避免处理头结点
Status insert_x( LinkedList head, ElemType x, int i ); // 在第i个位置进行插入
ElemType get( LinkedList head, int i ); // 查找位于第i位的元素
Status delete_x( LinkedList head, ElemType x ); // 删除值为x的元素
Status delete_x_i( LinkedList head, int i ); // 删除位于第i个位置的元素
int get_length( LinkedList head ); // 求单链表长度
bool increase( LinkedList head ); // 判断单链表是否非递减
Status move_min( LinkedList head ); // 移动最小值节点, 空间复杂度O(1)
Status min_out( LinkedList head ); // 按非递减顺序输出单链表中元素,并释放节点所占的存储空间,空间复杂度O(1)
Status exchange( LinkedList head, LinkedList p ); // 交换节点p和p的后继
#endif
- 头插法
思路:头部插入,不需要额外指针。获得逆序序列。
LinkedList create_by_head( const ElemType* arr, int n )
{
if( NULL == arr || n <= 0 )
{
std::cerr << "Invalid arguments!" << std::endl;
return NULL;
}
LinkedList head = new ListNode();
if( !head )
{
std::cerr << "Not enough space!" << std::endl;
return NULL;
}
for( int i = 0; i < n; ++i )
{
LinkedList cur = new ListNode( arr[i] );
if(!cur)
{
std::cerr << "Not enough space!" << std::endl;
return NULL;
}
cur->next = head->next;
head->next = cur;
}
return head;
}
- 尾插法
思路:需要维护一个尾部指针
LinkedList create_by_tail( const ElemType* arr, int n )
{
if( NULL == arr || n <= 0 )
{
std::cerr << "Invalid arguments" << std::endl;
return NULL;
}
LinkedList head = new ListNode();
if( !head )
{
std::cerr << "Not enough space!" << std::endl;
return NULL;
}
LinkedList tail = head;
for( int i = 0; i < n; ++i )
{
LinkedList cur = new ListNode( arr[i] );
if( !cur )
{
std::cerr << "Not enough space!" << std::endl;
return NULL;
}
tail->next = cur;
tail = cur;
}
return head;
}
- 销毁
思路:由于从头开始销毁会使链表断掉,所以,只能从尾部开始销毁。但是,单链表只能是从头部开始访问。所以如果直接写 O(N2) 的复杂度。换种思路,既然只能是从头开始访问,并且先访问的后销毁。显然会,这是一种“先进后出”的形式。考虑用栈做辅助数据结构。
Status destroy( LinkedList head )
{
if(!head)
{
std::cerr << "Invalid arguments" << std::endl;
return ERROR;
}
std::stack<LinkedList> stk;
LinkedList p = head->next;
while( p )
{
stk.push( p );
p = p->next;
}
while( !stk.empty() )
{
delete stk.top();
stk.pop();
}
return OK;
}
- 销毁-递归实现
思路:有了上面的思路,很自然过渡到递归的思路。本质还是用栈。
Status destroy1( LinkedList head )
{
if( head )
{
destroy1( head->next );
delete head;
}
return OK;
}
- 打印
思路:枚举
Status print( LinkedList head )
{
if( !head )
{
std::cerr << "Invalid arguments" << std::endl;
return ERROR;
}
LinkedList p = head->next;
while( p )
{
std::cout << p->data << " ";
p = p->next;
}
std::cout << std::endl;
return OK;
}
- 打印-非递归
思路:略。
注意:
参数传递时需要传递head->next
Status print1( LinkedList head )
{
if( head )
{
std::cout << head->data << " ";
print1( head->next );
}
return OK;
}
- 在第i个位置插入
思路:需要找到第i-1个位置。
注意:第i个位置可能不存在
Status insert_x( LinkedList head, ElemType x, int i )
{
if( NULL == head || i < 1 )
{
std::cerr << "Invalid arguments!" << std::endl;
return ERROR;
}
LinkedList p = head->next;
int j = 1;
while( p && j < i - 1 )
{
p = p->next;
++j;
}
if( p )
{
LinkedList cur = new ListNode( x );
if( !cur )
{
std::cerr << "Not enough space!" << std::endl;
return ERROR;
}
cur->next = p->next;
p->next = cur;
return OK;
}
else
{
std::cerr << i << " is not exits!" << std::endl;
return ERROR;
}
}
- 返回第i个位置的元素
思路:略
注意:第i个位置可能不存在
ElemType get( LinkedList head, int i )
{
if( !head )
{
std::cerr << "Invalid arguments!" << std::endl;
return ERROR;
}
LinkedList p = head->next;
int j = 1;
while( p && j < i )
{
p = p->next;
++j;
}
if(p)
{
return p->data;
}
else
{
std::cerr << i << " is not exits!" << std::endl;
return ERROR;
}
}
- 删除第i个位置的元素
思路:需要找到第i-1个位置的元素。维护一个pre指针即可。
注意:第i个位置可能不存在
Status delete_x_i( LinkedList head, int i )
{
if( !head )
{
std::cerr << "Invalid argumets!" << std::endl;
return ERROR;
}
LinkedList pre = head;
LinkedList p = head->next;
int j = 1;
while( p && j < i )
{
pre = p;
p = p->next;
++j;
}
if( p )
{
pre->next = p->next;
delete p;
p = NULL;
return OK;
}
else
{
std::cerr << i << " is not exists! " << std::endl;
return ERROR;
}
}
- 删除元素值为x的元素
思路:需要找到x前面的一个元素,维护一个pre指针即可。
注意:x可能不存在
Status delete_x( LinkedList head, ElemType x )
{
if( !head )
{
std::cerr << "Invalid arguments!" << std::endl;
return ERROR;
}
LinkedList pre = head;
LinkedList p = head->next;
while( p && p->data != x )
{
pre = p;
p = p->next;
}
if( p )
{
pre->next = p->next;
delete p;
p = NULL;
return OK;
}
else
{
std::cerr << x << " is not exits!" << std::endl;
return ERROR;
}
}
- 返回单链表长度
思路:枚举
int get_length( LinkedList head )
{
if( !head )
{
std::cerr << "Invalid arguments!" << std::endl;
return -1;
}
int length = 0;
LinkedList p = head->next;
while( p )
{
++length;
p = p->next;
}
return length;
}
- 判断单链表是否非递减
思路:维护pre指针,枚举判断pre和当前元素值的大小。
bool increase( LinkedList head )
{
if( !head )
{
std::cerr << "Invalid arguments!" << std::endl;
return false;
}
LinkedList pre = head->next; // pre指向第一个节点
if(!pre)
return false;
LinkedList p = pre->next;
while( p )
{
if( pre->data > p->data )
return false;
pre = p;
p = p->next;
}
return true; // 不存在逆序
}