1. 程式人生 > >單鏈表的建立,實現和操作

單鏈表的建立,實現和操作

#include<cstdio>
#include<algorithm>
#include<stack>
#include<iostream>
#include<malloc.h>
using namespace std;
typedef struct LNode
{
    int data;
    struct LNode *next;
} LinkList;
//注意,單鏈表頭節點不儲存資料
void InitList(LinkList *&head)//初始化單鏈表
{
    head=(LinkList*)malloc(sizeof(LinkList));
    head->next=NULL;
}
//下面是兩種建立單鏈表的方法
//其中頭節點為head融合在建立中,因提前建立,所以下方不使用
void CreateListA(LinkList *&head,int a[],int n)//尾插法,依次將元素放在前一個元素後方
{
    LinkList *r,*s;//建立兩個指標
    /*head=(LinkList*)malloc(sizeof(LinkList));//為頭結點分配空間
    head->next=NULL;*/
    r=head;
    for(int i=0; i<n; i++)
    {
        s=(LinkList*)malloc(sizeof(LinkList));
        s->data=a[i];
        r->next=s;
        r=s;//是r不斷更新為所插入的下一個元素,再次進入迴圈
    }//通過for迴圈實現尾插法
    r->next=NULL;
}
void CreateListB(LinkList *&head,int a[],int n)//頭插法,邏輯順序與物理順序相反
{
    LinkList *s;
    /*head=(LinkList*)malloc(sizeof(LinkList));//分配空間
    head->next=NULL;*/
    s=head;
    for(int i=0; i<n; i++)
    {
        s=(LinkList*)malloc(sizeof(LinkList));
        s->data=a[i];
        s->next=head->next;
        head->next=s;//元素在插入的過程中新元素排在舊元素後面,所以邏輯物理順序相反
    }
}
void DestroyList(LinkList *&head)//銷燬單鏈表
{
    LinkList *pre=head,*p=head->next;//建立兩個指標,來回使用
    while(p!=NULL)
    {
        free(pre);
        pre=p;
        p=pre->next;
    }//逐一釋放空間
    free(pre);//釋放最後一個
}
bool ListEmpty(LinkList *&head)//判斷是否為空表(是否只含有一個頭節點,若是,則為空)
{
    return (head->next==NULL);//如果為空,則返回值為1
}
int ListLength(LinkList *head)//計算單鏈表長度
{
    int n=0;
    LinkList *p=head;
    while(p->next!=NULL)
    {
        n++;
        p=p->next;
    }
    return n;
}
void DisplayList(LinkList *head)//輸出線性表各個元素
{
    LinkList *p=head->next;//由於頭節點不儲存資料,所以從下一個開始
    while(p!=NULL)
    {
        cout<<p->data<<' ';
        p=p->next;
    }
    cout<<endl;
}
bool GetElem(LinkList *head,int i,int &e)//求線性表指定位置i的某個元素,將值賦給e,此處先判斷,如成功則賦值輸出
{
    LinkList *p=head;
    for(int j=0; j<i&&p!=NULL; j++)
    {
        p=p->next;
    }
    if(p==NULL)//判斷迴圈中斷的原因,若為p==NULL,則說明超出單鏈表範圍
        return false;
    else
    {
        e=p->data;
        return true;
    }
}
int  LocateElem(LinkList *head,int e)//找出哪一個位置的元素與e值相等,若不存在,輸出0
{
    LinkList *p=head->next;
    int i;
    for(i=1; p!=NULL&&p->data!=e; i++)
    {
        p=p->next;
    }
    if(p==NULL)//判斷終止條件
        return 0;//代表不存在,遍歷完畢
    else
        return i;
}
/*下面是單鏈表的插入和刪除操作,可以借用if判斷來得出插入或刪除值。
   也可直接呼叫函式*/
bool ListInsert(LinkList *&head,int i,int e)//插入元素在第i個位置插入元素e
{
    LinkList *p=head,*s;
    for(int j=0; j<i-1&&p!=NULL; j++)
    {
        p=p->next;
    }
    if(p==NULL)
        return false;
    else
    {
        s=(LinkList*)malloc(sizeof(LinkList));
        s->data=e;
        s->next=p->next;
        p->next=s;//畫圖吧,畫圖好理解
        return true;
    }
}
bool ListDelete(LinkList *&head,int i,int &e)//刪除線性表第i個元素,將刪除元素的值賦給e
{
    LinkList *p=head,*q;
    for(int j=0; j<i-1&&p!=NULL; j++)
    {
        p=p->next;
    }
    if(p==NULL)
        return false;
    else
    {
        q=p->next;
        if(q==NULL)//判斷p下一個節點是否為空,若為空則不滿足條件
            return false;
        e=q->data;//將要刪除的元素賦給e
        p->next=q->next;
        free(q);
        return true;
    }
}
void nixv(LinkList *&head)//就地逆序
{
   LinkList *p,*r;//
   p=head->next;
   head->next=NULL;
   while(p!=NULL)
   {
       r=p->next;
       p->next=head->next;
       head->next=p;
       p=r;//此處關鍵,建議畫圖
   }
}
//以下是函式呼叫測試
int main()
{
    LinkList *head;//初定義
    InitList(*&head);//頭節點
    cout<<ListEmpty(*&head)<<endl;
    int n;
    cout<<"請輸入元素個數n"<<endl;
    cin>>n;
    int m;
    int a[100];
    for(int i=0; i<n; i++)
    {
        cin>>a[i];
    }
    CreateListA(*&head,a,n);//此處為尾插,頭插用法與此相同
    //個人認為可以用不斷插入的方法,這樣可以動態分配記憶體,不用提前開陣列依次填入
    DisplayList(*&head);//輸出測試
    cout<<"元素個數為"<<ListLength(head)<<endl;
    int e,z;
    cout<<"請輸入z,e,代表在第z位置插入元素e"<<endl;
    cin>>z>>e;
    ListInsert(*&head,z,e);//插入測試
    DisplayList(*&head);//輸出測試
    int qq;
    cout<<"請輸入qq,代表刪除第幾位置的元素"<<endl;
    cin>>qq;
    int zz;
    ListDelete(*&head,qq,zz);
    DisplayList(*&head);//輸出測試
    cout<<"刪除的元素是"<<zz<<endl;
    cout<<"逆序輸出"<<endl;
    nixv(*&head);
    DisplayList(*&head);
    return 0;
}