单链表

一、简单单链表

先上代码

Chain.h

#include<iostream>

template<class T>
class Chain;

template<class T>
class ChainNode
{
/*
要将私有成员数据或函数暴露给另一个类,
必须将后者声明为友元类。
*/
    friend class Chain<T>;
private:
    T data;
    ChainNode<T>* link;    
};

template<class T>
class Chain
{
private:
    ChainNode<T>* first;
/*
链表长度,即链表元素的个数
*/
    int n;
public:
    Chain(){first=NULL;n=0;}
    ~Chain();
    bool IsEmpty() const{return first==NULL;}
/*
非静态成员函数后面加const(加到非成员函数或静态成员后面会产生编译错误),
表示成员函数隐含传入的this指针为const指针,
决定了在该成员函数中,任意修改它所在的类的成员的操作都是不允许的(因为隐含了对this指针的const引用)
*/
    int Length() const{return n;}
    bool Find(int k,T& x) const;
    int Search(const T& x) const;
    bool Delete(int k,T& x);
    bool Insert(int k,const T& x);
    void Output() const;
};

  

  (1)由于ChainNode用到了友元类Chain;但是类Chain是在ChainNode后面声明的;所以要超前声明类Chain;

      template<class> class Chain
Chain.cpp

#include "Chain.h"
/*
删除链表中的所有节点
*/
template<class T>
Chain<T>::~Chain()
{
    ChainNode<T>* next;
    while(first)
    {
        next = first->link;
        delete first;
        first = next;
    }
}

/*
在链表中查找第k个元素
k是元素的下标
*/
template<class T>
bool Chain<T>::Find(int k,T& x) const
{
    if(n<1||k<0||k>n-1)
    {
        return false;
    }
    
    ChainNode<T>* current=first;
    for(int j=0;j<k;j++)
    {
        current=current->link;
    }
    x=current->data;
    std::cout<<x<<std::endl;
    return true;
}

/*
在链表中搜索
寻找x,如果发现x,则返回x的地址
如果x不在链表中,则返回-1
*/
template<class T>
int Chain<T>::Search(const T& x) const
{
    if(n<1)
    {
        return 0;
    }
    ChainNode<T>* current=first;
    for(int j=0;current;j++)
    {
        if(x==current->data)
        {
            std::cout<<j<<std::endl;
            return j;
        }
        current=current->link;
    }
    return -1;
}

/*
从链表中删除一个下标为k元素的x
*/
template<class T>
bool Chain<T>::Delete(int k,T& x)
{
    if(n==0||k<0||k>n-1)
    {
        return false;
    }

    ChainNode<T>* current=first;
    ChainNode<T>* pre=NULL;
    for(int j=0;j<k-1;j++)
    {
        current=current->link;
    }
    
    if(k==0)
    {
        first=first->link;
    }
    else
    {
        pre=current;
        current=current->link;
        pre->link=current->link;
    }
    x=current->data;
    delete current;
    current=NULL;
    n--;
    return true;
    
}

/*
向链表中插入元素
*/
template<class T>
/*
const T& x 
const在类型T前面,即传入的x不能重新赋值
*/
bool Chain<T>::Insert(int k,const T& x)
{
    if(k<0||k>n)
    {
        return false;
    }

    ChainNode<T>* current=first;
    ChainNode<T>* p = new ChainNode<T>;
    p->data=x;
    for(int j=0;j<k-1;j++)
    {
        current=current->link;
    }
    if(k>0)
    {
        if(k==n)
        {
            current->link=p;
            p->link=NULL;
        }
        else
        {
            p->link=current->link;
            current->link=p;    
        }
    }
    else 
    {
        p->link=first;
        first = p;
    }
    n++;
    return true;
}

template<class T>
void Chain<T>::Output() const
{
    ChainNode<T>* Node=first;
    while(Node)
    {
        std::cout<<Node->data<<" ";
        Node=Node->link;
    }
    std::cout<<std::endl;
}


int main(void)
{
    Chain<int> a;
    int e;
    a.Insert(0,10);
    a.Insert(0,11);
    a.Insert(0,15);
    a.Insert(2,12);
    a.Insert(2,14);
    a.Insert(a.Length(),16);
    a.Insert(a.Length(),17);
//    a.Insert(2,11);
    a.Output();
    a.Delete(0,e);
    a.Delete(a.Length()-1,e);
    a.Delete(2,e);
    a.Output();
    a.Search(10);
    a.Find(2,e);
    return 0;
}

  

  (1)注意删除和增加元素的时候for循环是for(int j=0;j<k-1;j++);注意是k-1;不同于查找;

    应为删除;增加元素的k;都是以0为下标开始的。

   

输出

[ztteng@ztteng Chain]$ ./Chain        
15 11 14 12 10 16 17 
11 14 10 16 
2
10

Makefile

-rwxrw-r--. 1 ztteng ztteng 2428 Oct 22 13:25 Chain.cpp
-rw-rw-r--. 1 ztteng ztteng  859 Oct 22 11:18 Chain.h
-rw-rw-r--  1 ztteng ztteng  621 Oct 22 12:35 Makefile
CC      := g++
#CCOPT := -g -Wall -O2
CCOPT := -g -Wall 

 
CURRENT_PATH := $(shell pwd)

INC_PATH := $(CURRENT_PATH)
#LIB_PATH := $(CURRENT_PATH)/lib
SRC_PATH := $(CURRENT_PATH)
OBJS_PATH := $(CURRENT_PATH)



SRC_FILE_DIR := $(wildcard $(SRC_PATH)/*.cpp) 
SRC_FILE :=$(notdir $(SRC_FILE_DIR))
OBJS_FILE := $(SRC_FILE:.cpp=.o)

OBJS:=$(OBJS_PATH)/$(OBJS_FILE)


 
TARGET := Chain

$(OBJS_PATH)/%.o:$(SRC_PATH)/%.cpp
    $(CC) $(CCOPT) -I$(INC_PATH) -c $^ -o $@
    
 
$(TARGET) : $(OBJS)
    $(CC) $(CCOPT) -I$(INC_PATH) -o $@ $^


.PHONY : clean
clean : 
    rm -rf $(TARGET)
    rm -rf $(OBJS)

  (1)makefile当时报错;

 Makefile:25: *** missing separator.  Stop.

 原因是从博客园复制下来的makefile不可用;是因为 命令必须以tab开头;而复制下来的命令不是tab开头所以报没有分割错误

 

posted @ 2013-10-22 13:33  z折腾  阅读(235)  评论(0编辑  收藏  举报