链表一种重要的数据结构,以下给出单链表的算法,用C语言说明算法,最后给出完整的C++封装。
C语言说明算法
定义单链表节点结构体
struct Node
{
//数据
int date;
//指向下一节点的指针
struct Node * next;
};下面是单链表的两种生成方法,头插法产生的单链表,数据存储顺序与数据输入的顺序刚好相反,尾插法数据存储顺序与头插法的相反,即为数据输入的顺序。
头插法生成单链表
//头插法插入元素后得到的链表中元素逆序
void CreateListF(Node *&L, int a[], int n){
Node *s;
int i;
L = (Node *)malloc(sizeof(Node));//申请一块内存空间
L->next = NULL;//头结点
for (i = 0; i < n; i++){
s = (Node *)malloc(sizeof(Node));
s->date = a[i];
s->next = L->next;//将L中存放的下一个节点的地址赋给S->next
L->next = s;//使L指向s本身
}
}尾插法生成顺序表
void CreateListB(Node *&L, int a[], int n){
Node *r, *s;
int i;
L = (Node*)malloc(sizeof(Node));
r = L;//将头结点作为尾节点
for (i = 0; i < n; i++){
s = (Node*)malloc(sizeof(Node));//每次都需重新申请空间(每次结束前都会将s申请的空间赋给r)
s->date = a[i];
r->next = s;//使r中地址域存储s节点的地址
r = s;//将s节点的地址赋给r(s所申请的空间给了r,隐含的将数据赋给了r)//地址运算效率更高
}
r->next = NULL;//插入完毕后尾节点地址域赋值为空
}删除链表
//删除链表
void DestroyList(Node *&L){
Node *pre = L, *p = L->next;
while (p != NULL){
free(pre);
pre = p;//pre得到下一个节点的地址
p = pre->next;//p指向下下个节点的地址(此时pre以为下一个即将释放的节点的地址)
}
free(pre);//最后判断为空时,退出循环释放最后一个节点空间
}
//判断链表是否为空
bool ListEmpty(Node *&L){
return (L->next == NULL);
}
//链表长度
int ListLength(Node *&L){
int count = 0;//计数器
Node *p = L;
while (p->next != NULL){//当不为空时便+1,直至退出循环
count++;
p = p->next;
}
return count;
}输出单链表
//输出单链表
void DisplayList(Node *&L){
Node *p = L->next;//用于遍历单链表的指针
while (p != NULL){//遍历输出
cout << p->date << ends;
p = p->next;
}
cout << endl;
}按位置查找,并返回值
//查找单链表中的某个值(按位置查找)
bool getElem(Node *&L, int i,int &res){//i为需查找的元素的位置,res用于返回值
int j = 0;//j用于记录找到的第一个位置
Node *p = L;
while (j < i&&p != NULL){
j++;
p = p->next;
}
//对退出的两种情况做讨论
if (p == NULL){
return false;
}
else{
res = p->date;
return true;
}
}按值查找,并返回元素位置
//查找值(按值查找)
int LocateList(Node *&L, int e){
int i = 0;//i用于记录位置
Node *p = L;
while (p != NULL&&p->date != e){
p = p->next;
i++;
}
//讨论退出的两种情况
//若p为空则返回0
if (p == NULL){
return 0;
}
//若找到则返回i
else{
return i;
}
}在位置i插入元素elem
//在第i个位置插入节点
void InsertNode(Node *&L, int i,int elem){
i--;//只需找到插入位置i的前一个节点
Node *p = L, *s;
int j = 0;
while (i!=j&&p->next != NULL){
j++;
p = p->next;
}
//讨论退出循环的两种情况
if (p->next == NULL){
cout << "It is empty,error number." << endl;
}
//找到位置,插入元素
else{
s = (Node *)malloc(sizeof(Node));
s->date = elem;
s->next = p->next;
p->next = s;
}
}删除位置i的节点
//删除第i个位置的节点
void DeleteNode(Node *&L, int i){
i--;
Node *p = L, *s;
int j = 0;
while (i != j&&p->next != NULL){
j++;
p = p->next;
}
if (p->next == NULL){
cout << "It is empty,error number." << endl;
}
else{
s = p->next;
p->next = p->next->next;//跳过需删除的节点
free(s);//释放需删除的节点的空间
}
}以上便是所有单链表C语言的实现,下面给出C++封装好的单链表,其中头插法和尾插法都能用,代码中使用了尾插法。
/*
*单链表的实现
*/
#include<iostream>
using namespace std;
const int MAX_N = 100;
typedef class Node
{
public:
int data;
class Node *next;
}ListNode;
class List
{
public:
//构建单链表并初始化(头插法)
/* List(int a[], int n){
ListNode *s;
int i;
L = (ListNode *)malloc(sizeof(ListNode));
L->next = NULL;
for (i = 0; i < n; i++){
s = (ListNode *)malloc(sizeof(ListNode));
s->data = a[i];
s->next = L->next;
L->next = s;
}
}*/
//构建并初始化(尾插法)
List(int a[], int n){
ListNode *p, *s;
int i;
L = (ListNode *)malloc(sizeof(ListNode));
p = L;
for (i = 0; i < n; i++){
s = (ListNode *)malloc(sizeof(ListNode));
s->data = a[i];
p->next = s;
p = s;
}
p->next = NULL;
}
//析构,释放空间
~List(){
ListNode *pre = L, *p = L->next;
while (p->next != NULL){
free(pre);
pre = p;
p = pre->next;
}
free(pre);
}
//判断是否为空
bool isEmpty(){
return (L->next == NULL);
}
//单链表长度
int getLength(){
ListNode *p = L;
int i = 0;
while (p->next != NULL){
i++;
p = p->next;
}
return i;
}
//输出单链表中元素
void DisplayList(){
ListNode *p = L->next;//指向第一个存有数据的节点(非头结点)
while (p != NULL){
cout << p->data << ends;
p = p->next;
}
cout << endl;
}
//按序号查找并返回数据值
bool getElem(int i,int &res){
ListNode *p = L;
int j = 0;
while (j != i&&p->next != NULL){
j++;
p = p->next;
}
if (j!=i&&p->next == NULL){//必须还有j!=i,否则最后一个节点无法访问
return false;
}
else{
res = p->data;
return true;
}
}
//按值查找并返回序号
int LocateElem(int &elem){
ListNode *p = L;
int i = 0;
while (p->data != elem&&p->next != NULL){
i++;
p = p->next;
}
if (p->data!=elem&&p->next == NULL){
return 0;
}
else{
return i;
}
}
//插入元素
void InsertElem(int i, int &elem){
i--;
ListNode *p = L, *s;
int j = 0;
while (j != i&&p->next != NULL){
j++;
p = p->next;
}
if (p->next == NULL){
cout << "error number." << endl;
}
else{
s = (ListNode *)malloc(sizeof(ListNode));
s->data = elem;
s->next = p->next;
p->next = s;
}
}
//删除元素
bool DeleteElem(int i,int &res){
i--;
ListNode *p = L, *s;
int j = 0;
while (j != i&&p->next != NULL){
j++;
p = p->next;
}
if (p->next == NULL){
return false;
}
else{
s = p->next;
/* if (s->next == NULL)
return false;*/
res = s->data;
p->next = p->next->next;
free(s);
return true;
}
}
private:
Node *L;
//返回头结点地址
};
int main()
{
//ListNode *m_node;
int n, res=0, a[MAX_N], i;
cout << "Input the length:" << ends;
cin >> n;
for (i = 0; i < n; i++){
cin >> a[i];
}
//创建单链表
List m_list(a, n);
//输出
m_list.DisplayList();
//判断空,非空返回长度
if (!m_list.isEmpty()){
cout << "it is not empty." << endl;
cout << "The length:" << m_list.getLength() << endl;
}
else{
cout << "It is empty." << endl;
}
//按序号查找并返回元素
cout << "Input number:" << ends;
cin >> i;
if (m_list.getElem(i,res)){
cout << "NO. " << i << " ,data is " << res << endl;
}
else{
cout << "error number or not contained." << endl;
}
//按值查找并返回序号
cout << "Input the data:" << ends;
cin >> res;
if (m_list.LocateElem(res) == 0){
cout << "Not contained." << endl;
}
else{
cout << "The location is No. " << m_list.LocateElem(res) << endl;
}
//插入元素
cout << "Input the number and data:" << ends;
cin >> i >> res;
m_list.InsertElem(i, res);
m_list.DisplayList();
//删除元素
cout << "Input number:" << ends;
cin >> i;
if (m_list.DeleteElem(i, res)){
cout << "The NO. " << i << " ,data: " << res << " is deleted." << endl;
m_list.DisplayList();
}
else{
cout << "Not contain this number." << endl;
}
return 0;
}测试运行
本文介绍了单链表这一重要数据结构,并通过C语言详细阐述了算法,包括头插法和尾插法生成单链表。最后,文章提供了完整的C++封装实现。

2062

被折叠的 条评论
为什么被折叠?



