单链表

单链表思路:
1、表示结点,一个数据域,一个链接域,可以采用结构体或者类表示,这里
使用结构体表示。为简单起见,数据类型设置为int。
2、用类表示单链表这个抽象数据类型,包含数据和操作。
1)由于需要一个起始的链表头来开始建立链表,则需声明一个保护类型的指针。
2)建立一个类之后首先需要设定类的构造函数和析构函数。
3)然后是建立单链表,输出单链表。
4)插入、删除结点。
5)辅助函数:判断是否为空链表的函数;定位到给定的索引处。

单链表的结点用结构体来表示:

1
2
3
4
5
struct  LinkNode
{
    int data;   //数据域
    LinkNode *link; //结点本身的链接域
};

单链表的抽象数据类型用类表示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class LinkList
{
private:
    LinkNode *head; //链表头指针,位置不可以改变,建立该链表的时候确定
public:
    LinkList(){}    //构造函数
    ~LinkList();    //析构函数
 
    /*----------------建立、输出单链表--------------*/
    void InitLinkList();        //建立单链表
    void OutputLinkList();      //输出单链表
     
 
    /*----------------插入、删除结点-------------*/
    bool InsertNode(int data,int index);    //插入结点
    bool DeleteNode(int index); //删除结点
};

 下面介绍单链表的几种关键算法,单链表的建立,输出,插入结点和删除结点:

建立单链表的算法:
1、输入一个值,然后将该值赋值给当前结点的数据域。
2、拉链:head不能改变,所以需要另外声明一个指针*last。
1)将该值赋值给这个新建结点指针的数据域。
2)采用后插法建立单链表
3、将链表指针的最后一个链接域赋值为NULL,容易忽略 head->link=NULL
编程经验:
1、在分配一个存储空间后,加上测试语句是好的编程实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void LinkList::InitLinkList()
{
    int data;   //输入的结点值,以999号结束
    cout<<"请输入单链表的结点值:"<<endl;
    cin>>data;
    LinkNode *last;     //head指针不可以改变位置
    head=new LinkNode;  //链表头指针,要在这里进行初始化,重要,链表的头指针不能改变
    if(head==NULL){cerr<<"分配错误!"<<endl;}
    last=head;
    while(data!=999)    //如果该值不为999,则拉链,不断重复该过程
    {
        LinkNode* NewNode=new LinkNode;     //新建一个结点,用于拉链
        if(NewNode==NULL){cerr<<"分配错误!"<<endl;}
         
        NewNode->data=data;    //附加头结点
        //NewNode=head->link;
        //head=NewNode;       //这两句是典型的错误
 
        last->link=NewNode;
        last=NewNode;         //这样也不行
        cin>>data;              //输入改值
    }
 
    last->link=NULL;
 
}

 输出单链表算法:
1、根据链表头指针,输出该链表指针所指向的数据域。
2、判断该指针是否为空,不为空,则向下推进一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
void LinkList::OutputLinkList()
{
    LinkNode *current=head->link;    //带附加头结点的链表
    if(current==NULL){cerr<<"分配错误!"<<endl;}
    cout<<"单链表为:"<<endl;
    while(current!=NULL)
    {
        cout<<current->data<<" ";
        current=current->link;   //向下推进一个位置
    }
    cout<<endl;
     
}

 插入结点算法:
1、在index位置插入元素,需要先找到第index个元素的位置。
2、插入该元素到index位置,可能出现的情况:
1)先定义一个插入的结点指针*current。
2)声明一个num,用来记录当前的位置和所给的index进行比较。
3)判断num是否等于所给的index值,如果等于,就进行结点的插入操作。
a)需要注意的是current要在index-1的位置。
b)如果不相等,则current位置推进一个位置。
c)最后判断如果num<index 则表明链表太短,这样的操作属于非法操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
bool LinkList::InsertNode(int data,int index)
{
    int num=0;      //用来记录当前的位置
    LinkNode *current=head; //辅助结点,必须进行初始化
    LinkNode *newNode=new LinkNode; //待插入结点
    newNode->data=data;  //将该值赋值给该结点值
 
    while(current!=NULL)
    {
        num++;  //由于带附加头结点,所以num先要加1,表示第一个结点
        if(index==num)     
        {
            newNode->link=current->link;
            current->link=newNode;           //这两句进行结点的插入操作
        }
        else
        {
            current=current->link;   //推进一个位置
        }
    }
 
    if(num<index)
    {
        cout<<"单链表长度太短"<<endl;
        return false;
    }
    else
    {
        return true;
    }
}
 
/*-----------------------------------------*/

 单链表删除算法:
1、删除给的索引处的结点。
2、需要定义个current指针和一个计数器num;
3、如果num等于给定的index,则需要声明另外一个表示要删除的结点的指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
bool LinkList::DeleteNode(int index)
{
    LinkNode *current=head; //循环指针
    int num=0;
 
    while(current!=NULL)
    {
        num++;      //由于带附加头结点,所以需要先将num加1
 
        if(index==num)
        {
            LinkNode *p=current->link;   //待删除的结点
            current->link=p->link;
            delete p;
        }
        else
        {
            current=current->link;
        }
    }
    if(index>num)
    {
        cout<<"单链表的长度太短"<<endl;
        return false;
    }
    else
    {
        return true;
    }
}

 

posted @ 2013-05-24 21:53  李VS超  阅读(277)  评论(0编辑  收藏  举报