C 有头结点链表的若干操作

比无头节点的要简单很多

创建

typedef struct Node {
    int data;
    struct Node * next;
} LNode, * LinkNode;

//创建,丝毫不用理会第一个节点特殊情况
void creatLink(LinkNode * q){
    int i;
    LinkNode e, p1;
    //头节点
    *q = (LinkNode)malloc(sizeof(LNode));
    (*q)->next = NULL;
    p1 = *q;
  
    for (i = 0; i < 10; i++) {
    	//创建新节点
        e = (LinkNode)malloc(sizeof(LNode));
        e->data = i+1;
        e->next = NULL;
        //把新节点接在链表中
        p1->next = e;
        p1 = e;
    }
}

输出

//输出,让过第一个头节点
void putout(LinkNode q){
    LinkNode p1 = q->next;
    while (p1) {
        printf("%d ", p1->data);
        p1 = p1->next;
    }
    printf("\n");
}

访问第i个元素

/*访问第i个元素,并且返回,以参数的方式返回了,这个就是C语言的局限了,
只能返回一个参数,不像别的能返回个元组什么的*/
Status findElement(LinkNode q, int i, int *e){
    if(i < 1) return ERR;
    LinkNode p1 = q->next;
    //很实在从1开始
    int n = 1;
    while (p1) {
    	//这个就是第几个了
        if(n == i) {
            *e = p1->data;
            return OK;
        }
        p1 = p1->next;
        n++;
    }
    return ERR;
}

在i个位置前插入

Status insertElement(LinkNode q, int i, int e){
    if(i < 1 || !q) return ERR;
    //前驱p2,后继p1
    LinkNode p1 = q->next, p2 = q;
    int n = 1;
    
    while (p1) {
    	//还是先找到第i个位置,以及在第i个位置上的元素和其前驱元素
        if(n == i){
            LinkNode element = (LinkNode)malloc(sizeof(LNode));
            element->data = e;
            element->next = NULL;
            //插入元素
            p2->next = element;
            element->next = p1;
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
    }
    return ERR;
}

删除第i个元素

//删除第i个元素
Status deleteElement(LinkNode *q, int i, int *e){
    if(i < 1 || !((*q)->next)) return ERR;
   	//还是前驱后继
    LinkNode p1 = (*q)->next, p2 = (*q);
    int n = 1;
    while (p1) {
     	//找到第i个元素
        if(n == i)
        {
            (*e) = p1->data;
            p2->next = p1->next;
            free(p1);
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
    }
    return ERR;
}

头插

//头插
Status inserthead(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    //从头开始
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    element->next = p1->next;
    
    p1->next = element;
    return OK;
}

逆置

//逆置
void reverse(LinkNode *q){
    //将头节点独立出来,惯例找前驱后继
    LinkNode p1, p2;
    p1 = (*q)->next;
    (*q)->next = NULL;
    //将元素一次取出来,再按着头插法,插进去
    while (p1) {
        p2 = p1;
        p1 = p1->next;
        //每次取出来的元素都插在最前面
        p2->next = (*q)->next;
        (*q)->next = p2;
    }
}

尾插

//尾插
Status inserttail(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    //p1就是最后一个节点
    while (p1->next) {
        p1 = p1->next;
    }
    
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    element->next = NULL;
 	//接上
 	p1->next = element;
    return OK;
}

排序

//排序
void sort(LinkNode *q){
    LinkNode p1, p2;
    int temp;
    p1 = p2 = (*q)->next;
    
    //选择
//    for (; p1->next; p1 = p1->next) {
//        for (p2 = p1->next; p2; p2 = p2->next) {
//            if(p1->data > p2->data){
//                temp = p2->data;
//                p2->data = p1->data;
//                p1->data = temp;
//            }
//        }
//    }
    
    //冒泡 每趟只能遍历到最后,有些许浪费
    for (; p1->next; p1 = p1->next) {
        for (p2 = (*q)->next; p2->next; p2 = p2->next) {
            if(p2->data > p2->next->data){
                temp = p2->data;
                p2->data = p2->next->data;
                p2->next->data = temp;
            }
        }
    }
}

两个有序链表合并在一起,合并在一起的链表也要有序

//la和lb递增,归并起来lc
LinkNode combine2Links(LinkNode *q1, LinkNode *q2){
    //LinkNode =(* LNode)就是一个指针
    //把两个链表的第一个有数字的结点取出来,
    LinkNode p1 = (*q1)->next;
    LinkNode p2 = (*q2)->next;
    //我现在认为链表1就是合并成新的链表
    LinkNode L = *q1;
    //第二个链表的头结点于我来说莫得用了
    free(*q2);
    //遍历p1和p2,哪个小先放哪个
    while (p1 && p2) {
        if(p2->data > p1->data){
            L->next = p1;
            p1 = p1->next;
        }else{
            L->next = p2;
            p2 = p2->next;
        }
        L = L->next;
    }
    //最后剩下哪个全接上去
    if(p2){
        L->next = p2;
    }
    if(p1){
        L->next = p1;
    }
    //返回链表1
    return *(q1);
}

找出链表中数据最大的节点并返回

LinkNode findmax(LinkNode q){
    LinkNode p1 = q->next, max = NULL;
    //记录值
    int m = 0;
    while (p1) {
    	//只要发现比它大的,记录节点也刷新值
        if(m < p1->data){
            m = p1->data;
            max = p1;
        }
        //往后走
        p1 = p1->next;
    }
    return max;
}

链表中最小的节点放在最前面

//将链表最小节点移动到链表最前面
void insertMinNode(LinkNode *head){
	//遍历的时候前驱后继
    LinkNode p1 = (*head)->next;
    LinkNode p = (*head);
    //最小点的前驱后继
    LinkNode minPreNode = NULL, minNode = NULL;
    //初值
    int min = p1->data;
    //动起来
    while (p1) {
    	//只要发现还有小的就更新节点
        if(min > p1->data){
            min = p1->data;
            minNode = p1;
            minPreNode = p;
        }
        //驱动着往后走
        p = p1;
        p1 = p1->next;
    }
    //遍历完一次,留下的就是我们要的了,ps.链表中最好不要出现两个一样小的

	//删除原有的位置
    minPreNode->next = minNode->next;
    //添加到新的地方
    minNode->next = (*head)->next;
    (*head)->next = minNode;
}

有序链表中去除相同值的节点

//有序链表中去除相同值的节点
void deleteSimilarNode(LinkNode *head){
	//前驱后继
    LinkNode prenode = (*head)->next;
    LinkNode node = prenode->next;
    //往下走
    while (node) {
    	//要是相等就走后面的,前头等着直到走完
        if(prenode->data == node->data){
            prenode->next = node->next;
            free(node);
            node = prenode->next;
        }
        else
        //既然不相等,就都往后移动
        {
            prenode = node;
            node = node->next;
        }
    }
}

升序表里比x小的有几个

//升序表里比x小的有几个
int lessThanNode(LinkNode q, int x){
    LinkNode p1 = q->next;
    int n = 0;
    while (p1) {
    	//升序,碰见比x大的,那后面肯定都是大的,跳出
        if(p1->data >= x)
            break;
        n++;
        p1 = p1->next;
    }
    return n;
}
//
//  main.c
// 	单链表有头结点
//
//  Created by 赫凯 on 2018/10/23.
//  Copyright © 2018年 赫凯. All rights reserved.
//

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

#define OK 1
#define ERR 0

#define num 0

typedef int Status;

typedef struct Node {
    int data;
    struct Node * next;
} LNode, * LinkNode;

//创建,丝毫不用理会第一个节点特殊情况
void creatLink(LinkNode * q){
    int i;
    LinkNode e, p1;
    
    *q = (LinkNode)malloc(sizeof(LNode));
    (*q)->next = NULL;
    p1 = *q;
    
    for (i = 0; i < num; i++) {
        e = (LinkNode)malloc(sizeof(LNode));
        e->data = i+1;
        e->next = NULL;
        p1->next = e;
        p1 = e;
    }
}
//输出,让过第一个头节点
void putout(LinkNode q){
    LinkNode p1 = q->next;
    while (p1) {
        printf("%d ", p1->data);
        p1 = p1->next;
    }
    printf("\n");
}
//访问第i个元素
Status findElement(LinkNode q, int i, int *e){
    if(i < 1) return ERR;
    LinkNode p1 = q->next;
    int n = 1;
    while (p1) {
        if(n == i) {
            *e = p1->data;
            return OK;
        }
        p1 = p1->next;
        n++;
    }
    return ERR;
}
//在i个位置前插入
Status insertElement(LinkNode q, int i, int e){
    if(i < 1 || !q) return ERR;
    LinkNode p1 = q->next, p2 = q;
    int n = 1;
    
    while (p1) {
        if(n == i){
            LinkNode element = (LinkNode)malloc(sizeof(LNode));
            element->data = e;
            element->next = NULL;
            
            p2->next = element;
            element->next = p1;
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
        
    }
    return ERR;
}
//删除第i个元素
Status deleteElement(LinkNode *q, int i, int *e){
    if(i < 1 || !((*q)->next)) return ERR;
    
    LinkNode p1 = (*q)->next, p2 = (*q);
    int n = 1;
    while (p1) {
        if(n == i)
        {
            (*e) = p1->data;
            p2->next = p1->next;
            free(p1);
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
    }
    return ERR;
}
//头插
Status inserthead(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    element->next = p1->next;
    p1->next = element;
    
    return OK;
}
//尾插
Status inserttail(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    
    while (p1->next) {
        p1 = p1->next;
    }
    
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    p1->next = element;
    element->next = NULL;
    
    return OK;
}


int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    int e, i;
    
    LinkNode head = NULL;
    
    //创建
    creatLink(&head);
    putout(head);
    
    //头插尾插
    for (i = 0; i < 10; i+=2) {
        if(!inserthead(&head, i)) printf("头插失败");
        if(!inserttail(&head, i)) printf("尾插失败");
    }
    putout(head);
    
    //查找
    printf("\n查找\n");
    scanf("%d", &i);
    while (i) {
        if(findElement(head, i, &e)){
            printf("第 %d 位置上为 %d\n", i, e);
        }else{
            printf("输入参数错误!!!\n");
        }
        scanf("%d", &i);
    }
    //插入
    printf("\n输入位置及在之前插入的数字(输入两个数字)\n");
    scanf("%d %d", &i, &e);
    while (i) {
        if(insertElement(head, i, e)){
            putout(head);
        }else{
            printf("输入参数错误或者空链表\n");
        }
        getchar();
        scanf("%d %d", &i, &e);
    }
    //删除
    printf("\n输入位置删除元素\n");
    scanf("%d", &i);
    while (i) {
        if(deleteElement(&head, i, &e)){
            printf("第 %d 位置上为 %d 已经被删除\n", i, e);
            putout(head);
        }else{
            printf("输入参数错误或者空链表\n");
        }
        getchar();
        scanf("%d", &i);
    }
    
    
    return 0;
}

posted @ 2018-10-23 20:56  赫凯  阅读(30)  评论(0)    收藏  举报