链表

一、基本知识

  • 链表中各对象按线性顺序排序;
  • 链表与数组不同,数组按下表访问(随机),链表按指针访问(顺序)。

二、分类

1、单链表与双链表

  • 单链表:next指针;
  • 双链表:prev指针,next指针。

2、已排序与未排序

  • 已排序链表:链表的线性顺序对应表中各元素的线性顺序;
  • 未排序列表:元素按任意顺序出现。

3、环形与非环形

  • 环形链表:表头元素的prev指向表尾元素,表尾的next指向表头元素;
  • 非环形链表:表头元素无前驱,表尾元素无后继。

三、操作

  链表的主要操作有搜索、插入和删除。

  具体有两种实现链表的方式:

  • head指针指向的元素地址存放数据,链表为空时,head=NULL(为分配任何空间);链表不为空时,含有一个元素的量表如下:

  

  • head指向的地址不存放数据,链表为空时,分配了一个元素的空间。

(1) 无头指针

1、数据结构

  链表中每个对象包含关键字和指针。

struct Node{
    int data;
    Node* next;
};
Node* head=NULL;

2、搜索操作

  ListSearch采用简单的线性查找方法,找出线性表中第一个具有关键字k的元素,并返回指向该元素的指针。如果表中没有包含关键字为k的对象,则返回NULL。

Node* ListSearch( int k )
{
    Node* p = head;
    while (p != NULL && p->data != k)
        p = p->next;
    return p;
}

3、插入操作

  • 给定一个已设置了的新元素x,将x插入到链表的前段
void ListInsert(Node *x)
{
    x->next = head;
    head = x;
}
  • 在链表尾部位置插入数据元素dataInsert
void Insert( int dataInsert )
{
    Node *pInsert = new Node;
    pInsert->data = dataInsert;
    
    if (head==NULL)
    {
        pInsert->next = head;
        head = pInsert;
    }
    else
    {
        Node *p = head;
        Node *q = head->next;
        while (q != NULL)
        {
            p = q;
            q = q->next;
        }
        p->next = pInsert;
        pInsert->next = q;
    }
}

4、删除操作

  • 删除链表中的一个元素x
void ListDelete(Node* x)
{
    if (x==head)
    {
        head = x->next;
    }
    else
    {
        Node *p = head;
        while ( p->next != x)
            p = p->next;
        p->next = x->next;
    }
}
  • 删除链表中的数据元素datax

  先调用ListSearch(datax)函数得到该元素的指针,而后调用ListDelete函数删除该元素。

(2)有头链表

  设置哑对象(dummy object),将头节点设置为哑节点,要删除的节点肯定不会出现在链表头,简化边界条件的判定。

1、数据结构同上

2、创建链表

bool CreatNodeList()
{
    head = new Node;
    if (head == NULL)
    {
        return false;
    }
    else
    {
        head->data = 0;
        head->next = NULL;
        return true;
    }
}

3、搜索操作

Node *ListSearch2(int k)
{
    if ( head == NULL )
    {
        return head;
    }
    Node *p = head->next;
    while (p != NULL && p->data != k)
        p = p->next;
    return p;
}

4、插入操作

bool ListInsert2(Node *x)
{
    if ( head == NULL )
    {
        return false;
    }
    x->next = head->next;
    head->next = x;
return true; }

5、删除操作

bool ListDelete2(Node* x)
{
    if ( head == NULL )
    {
        return false;
    }
    else
    {
        Node *p = head;
        while ( p->next != x)
            p = p->next;
        p->next = x->next;
        return true;
    }
}

 (3)双向链表无头指针

1、结构

struct Node
{
    int data;
    Node *prev, *next;
};
Node* head = NULL;

2、查找

  与单链表相同

Node* ListSearch3(int k)
{
    Node* p = head;
    while (p!=NULL && p->data!=k)
        p = p->next;
    return p;
}

3、插入元素

void ListInsert3(Node* x)
{
    x->next = head;
    x->prev = NULL;
    if (head != NULL)
    {
        head->prev = x;
    }
    head = x;
}

4、删除元素

void ListDelete3(Node* x)
{
    if (x->prev != NULL)
    {
        (x->prev)->next = x->next;
    }
    else
    {
        head = x->next;
    }
    if (x->next != NULL)
    {
        (x->next)->prev = x->prev;
    }
}

(4)双链表带哑节点

  假设有链表L和一个对象nil[L](表示链表L的哑节点),将链表算法中每次对NULL的应用,用对nil[L]的应用代替,将一般的双向链表变成一个带哨兵的环形双向链表。

  • 哨兵元素nil[L]介于头节点和尾节点之间;
  • nil[L]的next指针指向链表的头,prev指针指向表尾;
  • 链表中第一个元素的prev指针指向nil[L],表尾的next指针指向nil[L]。

1、创建

bool CreatNodeList2()
{
    head = new Node;
    if (head == NULL)
    {
        return false;
    }
    else
    {
        head->data = 0;
        head->next = head;
        head->prev = head;
        return true;
    }
}

 

2、搜索

Node* ListSearch4(int k)
{
    Node* p = head->next;
    while (p!=NULL && p->data!=k)
        p = p->next;
    return p;
}

3、插入

void ListInsert4(Node* x)
{
    x->next = head->next;
    (head->next)->prev = x;
    head->next = x;
    x->prev = head;
}

4、删除

void ListDelete4(Node* x)
{
    (x->prev)->next = x->next;
    (x->next)->prev = x->prev;
}

 

posted on 2017-03-02 19:56  Valenpqq  阅读(131)  评论(0)    收藏  举报