单链表的基本操作

单链表的基本操作:

单链表的初始化、创建、插入、删除


声明

以下基本操作是对408数据结构伪代码的基本复现。当涉及到真正改变链表元素的操作时,伪代码的函数变量前需加“&”以实现解引用

一、定义单链表的数据类型

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

二、初始化单链表

即生成一个只有头指针的头结点(即将头节点的指针指空即可)
头节点:链表第一个不带数据域的结点
首结点:链表第一个带数据域的结点

linkList init_List(linkList head){
    head = (linkList)malloc(sizeof(Node));
    if(!head) {
        printf("内存分配失败");
        exit(0);
    }
    head->next = NULL;
}

三、创建单链表

1、头插法

linkList hc_List(linkList L){
    //初始化链表,若定义了初始化函数则可省略
    // L = (linkList)malloc(sizeof(Node));
    // L->next = NULL;

    int val;
    printf("请输入单链表的值(输入617退出创建单链表哦):\n");
    while(val != 617){
        scanf("%d", &val);

        Node *pNew = (linkList)malloc(sizeof(Node));
        pNew->data = val;
        pNew->next = L->next;
        L->next = pNew;
    }
    return L;
}

2、尾插法

思想:定义一个伪头结点,将每次新建的结点链在伪头结点的后面。在首结点创建之前,伪头结点即头结点,创建结点后,伪头结点后移

linkList rc_List(linkList L){
    //初始化链表,若定义了初始化函数则可省略
    // L = (linkList)malloc(sizeof(Node));
    // L->next = NULL;

    Node *pNew, *pTail=L;

    int val;
    printf("请输入单链表的值(输入617退出创建单链表哦):\n");
    while(val != 617){
        scanf("%d", &val);

        pNew = (linkList)malloc(sizeof(Node));
        pNew->data = val;
        pTail->next = pNew;
        pTail = pNew;
    }
    pTail->next = NULL;
    return L;
}

四、单链表的遍历

1、顺序遍历

void trv_List(linkList L){
    Node *pNode = L->next;
    printf("\n单链表为:");
    while (pNode){
        printf("%d ", pNode->data);
        pNode = pNode->next;
    }
}

2、逆序遍历

void anti_trv_List(linkList L){
    Node *pNode = L->next;
    if(pNode->next)
        anti_trv_List(pNode);
    printf("%d ", pNode->data);
}

五、单链表的查找

1、按值查找

返回的是该值在链表对应的位置

int val_search_List(linkList L, int val){
    int pos = 0;
    Node *pNode = L->next;

    while (pNode!=NULL && pNode->data!=val){
        pNode = pNode->next;
        pos++;
    }
    return pos+1;
}

2、按序号查找

返回的是该序号在链表中对应的结点

linkList index_search_List(linkList L, int pos){
    int val=0;
    Node *pNode = L->next;

    while(pNode!=NULL && pos>0 && pos>val+1 && pos<sizeof(L)){
        pNode = pNode->next;
        val++;
    }
    return pNode;
}

六、单链表的插入

在第i个位置插入(在p结点前插入q结点)

linkList index_insert_List(linkList L, int pos, int val){
    int i=0;
    Node *pNode=L, *New;

    if(pos<0 && pos>sizeof(L)){
        printf("插入位置无效");
        exit(0);
    }
    while (pNode &&  (pos-1)>i){
        pNode = pNode->next;
        ++i;
    }
    New = (linkList)malloc(sizeof(Node));
    New->data = val;
    New->next = pNode->next;
    pNode->next = New;
}

七、单链表的删除

1、删除第i个位置的值

linkList index_delete_List(linkList L, int i){
    int i=0, val;
    Node *pNode=L, *qNode;

    if(pos<0 || pos> sizeof(L) || !pNode){
        printf("删除位置不合法,删除失败");
        exit(0);
    }
    while (pNode && pos-1>i){
        pNode = pNode->next;	//pNode移动到第i个结点前
        ++i;
    }
    qNode = pNode->next;		//qNode指向第i个结点
    pNode->next = qNode->next;
    val = pNode->data;
    free(qNode);
}

2、删除所有值为val的结点

思想:用pNode遍历整个单链表,用preNode指向pNode结点的前驱结点,用qNode删除结点
若pNode找到值为val的结点,用qNode指向该结点,然后pNode下移,preNode指向移动后的pNode即可

void del_val_List(linkList L, int val){
    Node *preNode=L, *qNode, *pNode=L->next;
    while (pNode){
        if(pNode->data == val){
            qNode = pNode;
            pNode = pNode->next;
            preNode->next = pNode;
            free(qNode);
        } else{
            preNode = pNode;
            pNode = pNode->next;
        }
    }
}

3、删除链表中的最小值

思想:用pNode遍历整个单链表,用preNode指向pNode结点的前驱结点,用minPre指向最小值结点的前驱,minNode指向最小值结点结点

  • pNode一边扫描一边比较,一旦找到比minNode值大的结点,马上另minNode、minPre与pNode、preNode的指向相同,然后pNode、preNode下移
    在这里插入图片描述
linkList del_min_List(linkList L){
    Node *preNode=L, *pNode=preNode->next;
    Node *minPre=preNode, *minNode=pNode;

    while (pNode){
        if(minNode->data > pNode->data){
            minNode = pNode;
            minPre = preNode;
        }
        preNode = pNode;
        pNode = pNode->next;
    }
    minPre->next = minNode->next;
    free(minNode);
    return L;
}

八、原地置逆单链表

思想:断开头结点(将头结点指向置空),用nextPNode存放pNode的下一个结点(以免用头插法插入头结点后pNode指向为空)。用头插法将pNode插入头结点后将nextPNode付给pNode,每次使用头插法之前将nextPNode下移
linkList reverse_List(linkList L){
    Node *pNode, nextPNode;
    pNode = L->next;
    L->next = NULL;
    while(pNode){
    	nextPNode = pNode->next;
    	pNode->next = L->next;
    	L->next = pNode;
    	pNode = nextPNode;
    }
    return L;
}

八、单链表的排序

直接插入排序

linkList sort_List(linkList L){
    Node *qNode, *pNode=L->next, *nextPNode=pNode->next;
    pNode->next = NULL;
    pNode = nextPNode;

	while(pNode){
		nextPNode->next = pNode->next;
		qNode = L;
		while(qNode->next && pNode->data>qNode->data)
			qNode = qNode->next;
		pNode->next = nextPNode->next;
		nextPNode->next = pNode;
		pNode = nextPNode;
	}
}

源码

待续

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值