leetcode【数据结构简介】《链表》卡片——单链表

单链表简介

单链表中的每个结点不仅包含值,还包含链接到下一个结点的引用字段。通过这种方式,单链表将所有结点按顺序组织起来。
在这里插入图片描述
蓝色箭头显示单个链接列表中的结点是如何组合在一起的。

结点结构

//definition for singly-linked list.
struct SinglyListNode{
    int val;
    SinglyListNode *next;
}

在大多数情况下,我们将使用头结点(第一个结点)来表示整个列表。

与数组不同,我们无法在常量时间内访问单链表中的随机元素。 如果我们想要获得第 i 个元素,我们必须从头结点逐个遍历。 我们按索引访问元素平均要花费 O(N) 时间,其中 N 是链表的长度。

单链表的添加操作

单链表的删除操作

程序练习:设计链表

typedef struct NODE{
    int val;
    struct NODE *next;
} MyLinkedList;

/** Initialize your data structure here. */
MyLinkedList* myLinkedListCreate() {    
    MyLinkedList *L;    
    L = (MyLinkedList *)malloc(sizeof(MyLinkedList));    
    if(!L) return 0;    
    L->next = NULL;    
    return L;
}

/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
int myLinkedListGet(MyLinkedList* obj, int index) {    
    if(!obj) return 0;    
    MyLinkedList *p; 
    int i=0;    
    p = obj->next;    
    while(p!=NULL && i<index){        
        i++;        
        p = p->next;    
    }    
    if(!p) return -1;    
    return p->val;
}

/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {     
    MyLinkedList * s = (MyLinkedList *)malloc(sizeof(MyLinkedList));    
    s->val = val;    
    s->next = obj->next;    
    obj->next = s;
}


/** Append a node of value val to the last element of the linked list. */
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
    MyLinkedList * s = obj;
    while(s->next!=NULL) s = s->next;
    MyLinkedList * p = (MyLinkedList *)malloc(sizeof(MyLinkedList));
    p->val = val;
    p->next = NULL;
    s->next = p;
}

/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
    MyLinkedList * p = (MyLinkedList *)malloc(sizeof(MyLinkedList));
    p->val = val;
    MyLinkedList * s = obj; int i=0;
    if(i<0) myLinkedListAddAtHead(obj, val);
    else{
        while(s->next!=NULL && i<index){
            i++;
            s = s->next;
        }
        p->next = s->next;
        s->next = p;
    }   
}

/** Delete the index-th node in the linked list, if the index is valid. */
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
    MyLinkedList *s = obj; int i=0;
    while(s->next!=NULL && i<index){
        s = s->next;
        i++;
    }
    MyLinkedList * p = s->next;
    if(p){
        s->next = p->next;
        free(p);
    }
}

void myLinkedListFree(MyLinkedList* obj) {
    while(obj){
        MyLinkedList * p = obj->next;
        free(obj);
        obj = p;
    }
}

/**
 * Your MyLinkedList struct will be instantiated and called as such:
 * MyLinkedList* obj = myLinkedListCreate();
 * int param_1 = myLinkedListGet(obj, index);
 
 * myLinkedListAddAtHead(obj, val);
 
 * myLinkedListAddAtTail(obj, val);
 
 * myLinkedListAddAtIndex(obj, index, val);
 
 * myLinkedListDeleteAtIndex(obj, index);
 
 * myLinkedListFree(obj);
*/

在这里插入图片描述

注意

关于类型名

对结构体的修改 - 第一行struct后面的类型名需要补充完整。

typedef struct NODE{
    int val;
    struct NODE *next;
} MyLinkedList;

举本程序作为例子,上面这段代码声明了一个结构NODENODE不是一个变量名,而是一个新的类型,这个类型名称通常称为结构标记符(structure tag)或标记符名称(tag name)。结构标记符的命名方式和我们熟悉的变量名相同。

值得注意的是,结构标记符可以和变量使用相同的名称,但最好不要这么做,因为这会使代码难以理解。

在这个结构例子中,结构的一个实例MyLinkedList是在定义结构时声明的。它是一个NODE类型的变量,只要使用变量名称MyLinkedList,它都包含两个结构成员:valnext

关于申请空间

不同于数组和字符串,申请空间时可以一个结点一个结点的申请,返回适当的空间到相应的地址即可。

关于释放空间

释放空间只能单个节点的释放,故,释放整个链表需要遍历链表。

发布了13 篇原创文章 · 获赞 2 · 访问量 274

猜你喜欢

转载自blog.csdn.net/AuthurWhywat/article/details/105130839