C 数据结构中单链表基本操作

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/dcrmg/article/details/83650528

C中的typedef

C中的typedef关键字作用是为一种数据类型定义一个新名字,这样做的目的有两个,一是给变量定义一个易记且意义明确的新名字,如:

typedef unsigned char BYTE;

把unsigned char类型自命名为BYTE。
另一个目的是简化一些比较复杂的类型声明,比如struct结构类型:

     typedef struct student  
    {  
        int age;  
        int class;  
    }stu;  
    stu stu_1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候
    struct student stu_1; //以上等价于这种定义,C中规定声明struct对象时需要加struct关键字  

 

使用typedef定义结构体指针


如下定义:

typedef struct TreeNode {
    int Element;
    struct TreeNode* LeftChild;
    struct TreeNode* RightChild;
} Node,*PtrToTreeNode;

等价于:

给结构体 TreeNode 起一个别名为 Node;

给结构体指针 TreeNode* 起一个别名为 PtrToTreeNode; 即PtrToTreeNode实际上是一个指针


单链表基本操作

链表是一种线性存储数据的结构(线性结构是一种数据的逻辑结构,其他还有树结构、图结构和集合结构)。链表的存储内容在逻辑上连续,但物理上不一定连续。单向链表的组成包括:

  • 表头(head):只有指针域,没有数据域;
  • 结点(node):数据域+指针域;
  • 表尾:只有数据域,没有指针域(指针为NULL);

单链表结点(node)的定义:

struct node{
    int num;
    struct node* Pnext;
}


C语言中链表的实现主要依靠结构体和指针。

实现单链表的 创建、打印、计算长度、删除指定结点、头尾插入、链表递增排序、逆序、清空链表等操作:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//定义单链表结点结构
typedef struct Node{
    int data;
    struct Node* next;
}node;

//创建带表头单向链表,表尾插入
node* createList(const int length){
    node *head,*helper;
    helper = head = (node *)malloc(sizeof(node));
    for(int i=0;i<length;i++){
        helper = helper->next = (node *)malloc(sizeof(node));
        helper->data = i;
    }    
    helper->next = NULL;
    return head;
}

//打印链表
void printList(const node* list1){
    const node* p=NULL;
    p = list1->next;   //有表头链表指向表头后的结点     
    while(p){
        printf("%d\n",p->data);
        p = p->next;
    }
}

// 求链表长度
int length_list(const node* list1){
    int n=0;
    if(list1->next==NULL){
        return n;
    }
    while(list1->next!=NULL){
        n+=1;
        list1=list1->next;
    }
    return n;
}

//删除数据域值为key的结点
node* delete_key(node* list1, int key){
    if(list1->next==NULL){
        return list1;   //如果为空直接返回
    }
    node* p, *del;
    for(p=list1;p->next!=NULL&&p->next->data!=key;p=p->next);
    if(p->next==NULL){
        return list1;  //如果到最后一个结点还没有匹配到key,返回list1
    }
    del = p->next;
    p->next=p->next->next;
    free(del);
    del = NULL;
    return list1;
}

//在头结点或尾结点插入数据key
node* insert_list(node* list1, int key, int head_or_end){
    node* insert_key = (node*)malloc(sizeof(node));
    insert_key->data = key;   
    if(head_or_end){
        insert_key->next = list1->next;
        list1->next = insert_key;
        return list1;        
    }
    else{
        node* p = list1;
        for(p = list1; p->next!=NULL;p=p->next);
        p->next = insert_key;
        insert_key->next = NULL;
        return list1;        
    }    
}

//单链表排序(表头到表尾增大)
node* sort_list(node* list1){
    int length = length_list(list1);
    if(length==0){  //长度为0表示空链表,返回
        return list1;
    }   
    for(int i=1;i<length;i++){
        node* p = list1->next;       
        for(int j=0;j<length-i;j++){
            if(p->data>p->next->data){
                p->data+=p->next->data;
                p->next->data = p->data - p->next->data;
                p->data = p->data - p->next->data;
            }
            p=p->next;            
        }               
    }
    return list1;
}

//单链表逆序
node* reverse_list(node* list1){
    if(list1==NULL||list1->next==NULL){
        return list1;
    }
    node *p1, *p2, *p3;
    node *head = (node*)malloc(sizeof(node));
    p1 = list1;
    p2 = p1->next;
    while(p2!=NULL){
        p3 = p2->next;
        p2->next = p1;
        p1 = p2;
        p2 = p3;
    }
    list1->next->next=NULL;  
    head->next = p1;
    list1 = head;
    return list1;
}

//清空单链表
void delete_all(node* list1){
    node* p1=NULL,*p2 = NULL;
    p1 = list1->next;    
    while(p1->next!=NULL){
        p2 = p1->next;
        free(p1);
        p1 = p2;
    }
    free(p2);   
    list1->next=NULL;        
}

void main()
{
    node* List1 =createList(5);  //创建链表
    printList(List1);   //打印链表   
    printf("%d\n",length_list(List1));  //链表长度
    List1 = delete_key(List1,3);  //删除链表结点
    List1 = insert_list(List1,66,1);  //头结点插入数据
    List1 = insert_list(List1,77,0);  //尾结点插入数据
    List1 = sort_list(List1);    //链表递增排序
    printList(List1);
    List1 = reverse_list(List1);  //链表逆序
    printList(List1);          
    delete_all(List1);  //清空销毁链表
    printf("%d\n",length_list(List1));
    return;
}

补充两个操作: 头插法和查找中间结点

// 表头插入
node* create_list_headIN(const int length){
    node* head = (node*)malloc(sizeof(node));
    node* p;    
    for(int i=0;i<length;i++){
        p = (node*)malloc(sizeof(node));
        p->data = i;         
        p->next = head->next;
        head->next = p;            
    }
    head ;
    return head;
}

//查找链表中间结点
node* middle_node(node* list1){
    node *p1,*p2;
    p1 = p2 = list1;
    while(p2 && p2->next){
        p1 = p1->next;
        p2 = p2->next->next;
    }
    printf("\n%d\n",p1->data);
    return p1;
}

猜你喜欢

转载自blog.csdn.net/dcrmg/article/details/83650528