数据结构:链式表ADT的实现

        链表适用于插入或删除操作频繁,存储空间需求不定的情形。链表分很多种,有单链表、双链表、循环链表等,这里我以单链表为例,实现单链表的ADT。

        单链表是一种最简单的链表表示,也叫作线性链表。用它来表示线性表时,用指针表示节点间的逻辑关系。因此单链表的一个存储节点包含两部分:

                                         

       其中,data部分称为数据域,用于存储线性表中的一个数据元素,其数据类型由应用问题决定。link部分称为指针域或链域,用于存放一个指针,该指针表示该链表中下一个结点的开始存储地址。一个线性表的单链表结构如下图所示:

     

       其中,链表的第一个结点的地址可以通过链表的头指针first找到,其他结点的地址则在前驱节点的link域中,链表的最后一个结点没有后继,link内容为NULL。

       单链表的特点是长度可以很容易的扩充。链表的元素之间只在逻辑上相邻,在存储位置不一定相邻。                                     

下面给出来链式表ADT的C++实现:

一、顺序表的基本操作

1.链表置空操作

//链表置空
void LinkList::MakeEmpty(){
    //删除列表中处表头节点外的其他所有节点
    LinkNode *q;
    while(first->link!=NULL){
        q = first->link;//将一个节点从链中“摘下”
        first->link = q->link;
        delete q;//释放
    }
}

2.求链表长度操作

//求长度
int LinkList::Length(){
    LinkNode *q = first;
    int Count = 0;
    while(q->link!=NULL){
        Count++;
        q = q->link;
    }
    return Count;
}

3.查找操作

//查找
LinkNode* LinkList::Search(T x){
    LinkNode *p = first->link;
    while(p!=NULL&&p->data!=x){
        p = p->link;
    }
    return p;
}

4.定位操作

//定位
LinkNode* LinkList::Locate(int i){
    LinkNode *p=first;
    int j=0;//j计数
    if(i<0) return NULL;
    while(p!=NULL&&j<i){
        p = p->link;
        j++;
    }
    return p;
}

5.插入操作

//插入
//找到第i-1个元素,使x成为其后继,其原来的后继成为x的后继
bool LinkList::Insert(int i,T x){
    LinkNode *p = Locate(i-1);
    if(p==NULL){return false;}
    LinkNode *newnode = new LinkNode(x);
    if(newnode==NULL){
        cerr<<"内存分配错误!"<<endl;
        exit(1);
    }
    newnode->link = p->link;
    p->link = newnode;
}

6.删除操作

//删除
bool LinkList::Delete(int i,T x){
    LinkNode *p = Locate(i-1),*q;
    if(p==NULL||p->link==NULL){
        return false;
    }
    q = p->link;
    p->link = q->link;//重新链接
    x = q->data;
    delete q;
    return true;
}

7.输入操作

//输入
void LinkList::InputList(T EndTag){
    LinkNode *newnode,*r;
    T val;
    first == new LinkNode();//生成头结点
    if(first==NULL){cerr<<"存储分配错误!"<<endl;exit(1);}
    cout<<"请输入链表节点的元素:";
    cin>>val;//读入数据元素
    r = first;//r总是指向目前链表的最后一个结点
    while(val!=EndTag){
        newnode = new LinkNode(val);//申请空间,读入存储元素
        if(newnode==NULL){
            cerr<<"存储分配错误!"<<endl;
            exit(1);
        }
        r->link = newnode;//链接到最后面
        r = newnode;//刚链上的结点成为最后一个结点
        cin>>val;//读入数据元素
    }
    r->link = NULL;
}

8.输出操作

void LinkList::PrintList(){
    LinkNode *p=first->link;
    while(p!=NULL){
        cout<<p->data<<endl;
        p = p->link;
    }
}

二、完整的ADT和函数操作

1.数据结构的定义和基本操作函数的声明

/*
链式表ADT
*/

#include <iostream>
#include <stdlib.h>
#include <cstdlib>
using namespace std;

typedef int T;
class LinkList;//前视定义,否则友元类无法定义
class LinkNode{//链表节点类的定义
    friend class LinkList;
public:
    LinkNode *link;
    T data;
public:
    LinkNode(LinkNode *ptr=NULL){link=ptr;}
    LinkNode(T &item,LinkNode *ptr=NULL){
        data = item;
        link = ptr;
    }
    ~LinkNode(){};
};

class LinkList{
public:
    LinkNode *first;//指向链表头的指针
public:
    LinkList(){first = new LinkNode();}//带头节点的构造函数
    LinkList(T &x){//不带头节点的构造函数
        first = new LinkNode(x);
    }
    ~LinkList(){MakeEmpty();delete first;}//析构函数
    void MakeEmpty();//链表置空
    int Length();//求链表长度
    LinkNode* GetHead(){return first;}
    LinkNode* Search(T x);
    T GetData(int i);//返回第i个元素的值
    LinkNode* Locate(int i);//返回第i个元素的地址(指针)
    bool Insert(int i,T x);//在第i个元素后插入元素x
    bool Delete(int i,T x);//删除第i个元素
    int IsEmpty(){return (first->link==NULL?1:0);}
    void InputList(T x);//建立链表,x是输入结束的标志
    void PrintList();//打印链表
};

2.操作函数的具体实现

//链表置空
void LinkList::MakeEmpty(){
    //删除列表中处表头节点外的其他所有节点
    LinkNode *q;
    while(first->link!=NULL){
        q = first->link;//将一个节点从链中“摘下”
        first->link = q->link;
        delete q;//释放
    }
}

//求长度
int LinkList::Length(){
    LinkNode *q = first;
    int Count = 0;
    while(q->link!=NULL){
        Count++;
        q = q->link;
    }
    return Count;
}

//查找
LinkNode* LinkList::Search(T x){
    LinkNode *p = first->link;
    while(p!=NULL&&p->data!=x){
        p = p->link;
    }
    return p;
}

//定位
LinkNode* LinkList::Locate(int i){
    LinkNode *p=first;
    int j=0;//j计数
    if(i<0) return NULL;
    while(p!=NULL&&j<i){
        p = p->link;
        j++;
    }
    return p;
}

//插入
//找到第i-1个元素,使x成为其后继,其原来的后继成为x的后继
bool LinkList::Insert(int i,T x){
    LinkNode *p = Locate(i-1);
    if(p==NULL){return false;}
    LinkNode *newnode = new LinkNode(x);
    if(newnode==NULL){
        cerr<<"内存分配错误!"<<endl;
        exit(1);
    }
    newnode->link = p->link;
    p->link = newnode;
}

//删除
bool LinkList::Delete(int i,T x){
    LinkNode *p = Locate(i-1),*q;
    if(p==NULL||p->link==NULL){
        return false;
    }
    q = p->link;
    p->link = q->link;//重新链接
    x = q->data;
    delete q;
    return true;
}

//输入
void LinkList::InputList(T EndTag){
    LinkNode *newnode,*r;
    T val;
    first == new LinkNode();//生成头结点
    if(first==NULL){cerr<<"存储分配错误!"<<endl;exit(1);}
    cout<<"请输入链表节点的元素:";
    cin>>val;//读入数据元素
    r = first;//r总是指向目前链表的最后一个结点
    while(val!=EndTag){
        newnode = new LinkNode(val);//申请空间,读入存储元素
        if(newnode==NULL){
            cerr<<"存储分配错误!"<<endl;
            exit(1);
        }
        r->link = newnode;//链接到最后面
        r = newnode;//刚链上的结点成为最后一个结点
        cin>>val;//读入数据元素
    }
    r->link = NULL;
}

void LinkList::PrintList(){
    LinkNode *p=first->link;
    while(p!=NULL){
        cout<<p->data<<endl;
        p = p->link;
    }
}

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页