数据结构:单链表基本操做

单链表学习:参考《大话数据结构》

涉及到单链表的基本操做有以下:html

int initList(linkList *);  //初始化一个单链表,具备头指针,头结点,头结点->next=NULL;
int createListHead(linkList *, int n);  //头插法建立一个链表,链表长度为n;
int createListTail(linkList *, int n);  //尾插法建立一个链表,链表长度为n;
int getlength(linkList *);  //获取单链表的长度;
int printList(linkList *);  //打印整个链表;
int getElem(linkList *,int i,ElemType *);  //获取链表中第i个位置处节点的数据元素;
int insertList(linkList *, int i, ElemType data);  //在链表的指定位置(i节点)插入一个节点,i的范围为1~length(链表总长度);
int insertListTail(linkList *, ElemType data);  //给链表追加一个节点,在最末尾处增长;
int deleteList(linkList *, int i, ElemType *data);  //删除指定位置(i节点)处的节点,i的范围为1~length(链表总长度);
int clearList(linkList *);  //删除整个链表,使头结点->next=NULL;数组

(一)ADT:数据结构

typedef int ElemType;
typedef struct Node {
    ElemType data;
    struct Node * next;
}Node;
typedef struct Node* linkList;

(二)初始化:int initList(linkList *L)函数

int initList(linkList *L)
{
    (*L) = (linkList)malloc(sizeof(Node));
    (*L)->next = NULL;
    printf("链表初始化成功\n");
    return 1;
}

初始化一个指向头节点的指针,使头指针->next=NULL,头指针->data不作处理;  学习

(三)建立一个单链表spa

int createListHead(linkList *L,int n) {
    linkList p;
    int i = 0;
    srand((int)time(0));
    for (i = 0; i < n; i++)
    {
        p= (linkList)malloc(sizeof(Node));
        p->data = rand() % 100;
        printf("testing:Node[%d]=%d\n",i+1,p->data);
        p->next = (*L)->next;
        (*L)->next = p;
    }
    printf("链表(头插法)建立成功\n");
    return 1;
}

说明:指针

一、图中的head表示头指针,而在建立单链表中的入参phead是指向指针的指针;即*phead等同于head,*head指向头节点;code

二、初始化和建立整表的函数中,为何入参是linkList *类型的参数呢,为何不是Node *类型的;以前个人理解是可使用Node*类型的入参,这样声明一个Node *head,这样在建立整表的函数中能够直接createList(head,10),直接传入头指针,可是尝试过之后,会在经过头指针访问各节点数据的时候,弹出错误窗口,缘由还不太清楚;htm

3(补充)在看《C和指针》258的时候,看到了这么一句话,好像能够解释为何须要传入链表的基本操做函数中的入参是一个指针类型的变量;blog

“i='a';*pi='a';**ppi='a';  //这三条语句具备一样的效果;i-整型变量,pi-指向i的指针,ppi-指向pi指针的指针;

在一条简单的对i赋值的语句就能够完成任务的状况下,为何还要使用更为复杂的涉及间接访问的方法呢?这是由于简单赋值并不老是可行,例如链表的插入。在那些函数中,咱们没法使用简单赋值,由于变量名在函数的做用域内部是未知的。函数所拥有的只是一个指向须要修改的内存位置的指针,因此要对该指针进行间接访问操做以访问须要修改的变量。

           

  

​
int createListTail(linkList *L, int n) {
    linkList p, temp;
    temp = (*L);
    int i;
    srand((int)time(0));
    for (i = 0; i < n;i++) {
        p = (linkList)malloc(sizeof(Node));
        p->data = rand() % 100;
        printf("testing:Node[%d]=%d\n", i + 1, p->data);
        p->next = NULL;
        temp->next = p;
        temp = p;
    }
    printf("链表(尾插法)建立成功\n");
    return 1;
}

​

(四)获取链表的长度

int getlength(linkList *L) {
    linkList p;
    int length=0;
    p = (*L)->next;//p指向第一个节点;
    while (p) {
        length++;
        p = p->next;
    }
    return length;
}

(五)打印整个链表

int printList(linkList *L) {
    linkList p;
    int i = 0;
    p = (*L)->next;//p指向第一个节点;
    printf("-----------打印整个链表-----------\n");
    if (p==NULL) {
        printf("这是一个空链表.\n");
    }
    while (p) {
        i++;
        printf("第%d个节点的数据data为=%d\n",i,p->data);
        p = p->next;
    }
    return 1;
}

(六)获取指定位置处的节点元素;

int getElem(linkList *L, int i, ElemType *getdata) {
    linkList p;
    p = (*L)->next;
    if (p == NULL)
    {
        printf("链表为空,请建立一个链表\n");
        *getdata = -1;
        return 0;
    }
    if (i < 1)
    {
        printf("您所查询的节点%d,应该大于0,请从新输入查询\n",i);
        *getdata = -1;
        return 0;
    }
    int j = 1;
    while (p&&j<i) {
        j++;
        p = p->next;
    }
    if (p == NULL)
    {
        printf("您所查询的节点%d,已经超出了数组的长度\n",i);
        *getdata = -1;
        return 0;
    }
    *getdata = p->data;
    printf("查询成功!\n", i);
    return 1;
}

(七)插入节点;

插入节点分为两种,一种是在链表的长度范围内插入节点,第二种是在链表的尾部追加一个节点;

假设链表的长度为10,第一种能够在1-10位置处插入节点,好比在第10个位置插入一个节点,则原先的第10节点变为了11节点,可是第二种是全部节点位置都不变,在第11个位置追加一个新的节点;

int insertList(linkList *L, int i, ElemType data)
{
    linkList p;
    linkList insNode;
    p = (*L);
    int j=0;
    // 链表为空,在第1个位置插入一个新的节点;
    if (p ->next == NULL) {
        printf("链表为空,默认在第一个位置插入一个节点.\n");
        insNode = (linkList)malloc(sizeof(Node));
        insNode->data = data;
        insNode->next = p->next;
        p->next = insNode;
        printf("节点插入成功.\n");
        return 1;
    }
    // 链表非空的状况下,能够在i=1~length的位置插入节点,若是超过了链表的长度,就会提示错误;
    // 其实若是在length+1的位置处插入一个新节点,就至关于在尾部追加一个节点,在本函数中会报错,能够单独实现一个函数;
    while(p && j<i-1) 
    {
        j++;
        p = p->next;
        //printf("j=%d\tp->data=%d\n", j, p->data);
    }
    if (p->next==NULL) {
        printf("您要插入的位置,超过了链表的长度 %d,请从新操做!\n",j);
        return 0;
    }
    insNode = (linkList)malloc(sizeof(Node));
    insNode->data = data;
    insNode->next = p->next;
    p->next = insNode;
    
    printf("节点插入成功\n");
    return 1;
}

(八)删除节点;

int deleteList(linkList *L, int i, ElemType *data)
{
    linkList p,pnext;
    int j = 0;
    p = (*L);
    if (p->next == NULL) {
        printf("链表为空,没法删除指定节点.\n");
        *data = -1;
        return 0;
    }
    while (p->next && j<i-1) {
        j++;
        p = p->next;
        //printf("j=%d\t p->data=%d\n",j,p->data);
    }//条件最多定位到最后一个节点;
    if ( p->next == NULL) {
        printf("您要删除的节点,超过了链表的长度 %d,请从新操做!\n", j);
        *data = -1;
        return 0;
    }
    pnext = p->next;
    p->next = pnext->next;
    *data = pnext->data;
    free(pnext);
    printf("节点删除成功\n");
    return 1;
}

(九)删除这个链表;

int clearList(linkList *L) {
    linkList p, temp;
    p = (*L)->next;//p指向第一个节点
    while (p) {
        temp = p;
        p = p->next;
        free(temp);
    }
    (*L)->next = NULL;
    printf("整个链表已经clear.\n");
    return 1;
}

数据结构 链表_单链表的接口定义

相关文章
相关标签/搜索