数据结构 - 线性表之单链表

本系列博客 以C语言为实现语言 个人总结,请持怀疑态度参考

这里写图片描述

要点总结
  • 头插
    要考虑到插入的是第一个节点的情况
  • 链表的删除节点的动作
    要考虑到链表有没有节点
  • 按值插入
    按值插入在链表中的数据是有序的时候差有意义
  • 排序
    链表的排序一般不是以数据为单位,而是以节点为单位。排序的过程可以转化为值不停的插入的过程。即把链表拆分为两个链表,一个链表中只有头节点,把另一个链表中的数据按值插入第一个链表中。
  • 逆置
    这个思路还是把链表拆开成两个链表 ,第一个链表除了头结点只有一个节点,第二个链表就是剩下的部分。然后把第二个链表的值依次插入到第一个链表的头结点之后。
  • 迭尾代器
    用迭代器的方法实现头插/尾插会更加简单。
  • 按值删除
    按值删除的思路有两中 ,一种是找到值的节点,让后把节点的后驱的值拷贝过来,让后删除后驱,相当于删除了节点,避免了需要寻找值的前驱;第二种是通过节点的next的节点的值比较,找到节点的前驱,剩下的就好办了。。

贴一下完整的C实现以及注释

//Slist.h  文件

#ifndef _SLIST_H_
#define _SLIST_H_
#include <stdio.h>
#include <malloc.h>
#include "assert.h"
#define ElemType int

typedef struct Node
{
    ElemType data;
    struct Node * next;
}Node,*PNode;

typedef struct List
{
    PNode first;
    PNode last;
    size_t size;
}List;

Node *creatNode();
void InitList(List *);
void push_back(List * mylist, ElemType x);
void push_front(List *mylist, ElemType x);
void show_list(List *mylist);
void pop_back(List *mylist);
void pop_front(List *mylist);
void insert_val(List *mylist,ElemType x);
Node *find(List *mylist, ElemType x);
size_t length(List *mylist);
bool delete_val(List *mylist, ElemType x);
void sort(List *mylist);
void resver(List *mylist);
void clear(List *mylist);
void destroy(List *mylist);


/***********************************/
/*迭代器算法*/
typedef Node * Iter;
Iter begin(List *list);
Iter end(List *list);
void insert(List list, Iter pos, ElemType x);
#endif


----------

//Slist.c 文件 

#include "Slist.h"

Node * creatNode()
{
    Node * node = (Node*)malloc(sizeof(Node));
    assert(node != NULL);
    return node;
}

void InitList(List * list)
{
    list->first = list->last =(Node*)malloc(sizeof(Node));
    assert(list->first != NULL);
    list->size = 0;

    list->first->next = NULL;  //考虑到在一个空链表头插的情况
}

void push_back(List * mylist, ElemType x)
{
    Node* s=creatNode();
    s->data = x;
    s->next = NULL;
    mylist->last->next = s;
    mylist->last = s;
    mylist->size++;
    return;
}

void push_front(List *mylist, ElemType x)
{
    Node *s = creatNode();
    s->data = x;
    s->next = mylist->first->next;
    mylist->first->next = s;
    mylist->size++;

    if (mylist->size==0)  //考虑到插入的是地一个节点  
    {
        mylist->last = s;
    }

    return;
}

void show_list(List *mylist)
{
    Node *p = mylist->first->next;  //头结点是没有数据的,头节点的第二个节点才有数据    
    while (p!=NULL)
    {
        printf("%d-->", p->data);
        p = p->next;
    }
    printf("end\n");
    return;
}

void pop_back(List *mylist)
{
    if (mylist->size==0)   //如果链表为空 
    {
        return;
    }

    Node *p = mylist->first;

    while (p->next != mylist->last)
    {
        p = p->next;
    }


    free(mylist->last);

    mylist->last = p;
    mylist->last->next = NULL;

    mylist->size--;
}

void pop_front(List *mylist)
{
    if (mylist->size == 0)   //如果链表为空 
    {
        return;
    }

    Node *p = mylist->first->next;  //保存第一个节点

    mylist->first->next = mylist->first->next->next;
    free(p);
    p = NULL;

    mylist->size--;

    if (mylist->size==0)   //如果把最后一个节点删了,就要考虑尾节点
    {
        mylist->last = mylist->first;
    }

    return;
}

void insert_val(List *mylist, ElemType x)
{
    Node * s = creatNode();
    s->data = x;
    s->data = NULL;

    Node*p = mylist->first;
    while (p->next!=NULL &&p->next->data<x)
    {
        p = p->next;
    }

    if (p->next==NULL)   //考虑到插在最后一个节点  
    {
        mylist->last = s;
    }

    s->next = p->next;
    p->next = s;

    mylist->size++; 

}

Node * find(List *mylist, ElemType x)
{
    Node *p = mylist->first->next;
    while (p!=NULL&&p->data==x)     //这里注意  判断条件的执行顺序   先判断p是不是NULL  
    {
        p = p->next;
    }
    return p;  //p其实包含了两种结果      p=NULL          p->data=x
}

size_t length(List *mylist)
{
    return mylist->size;
}

bool delete_val(List *mylist, ElemType x)
{
    if (mylist->size==0)
    {
        return false;
    }
//  Node *p = mylist->first->next;
//  while (p->next!=NULL&&p->next->data==x)
//  {
//      p=p->next;
//  }
//  if (p->next!=NULL)
//  {
//      Node *pp = p->next;
//      p->next = p->next->next;
//      free(pp);
//      if (p->next==NULL)
//      {
//          mylist->last = p;
//      }
//      mylist->size--;
//      return true;
//  }
//  else
//  {
//      return false;
//  }

    Node *p = find(mylist, x);
    if (p!=NULL)
    {
        if (p==mylist->last)   //如果最后一个节点
        {
            pop_back(mylist);
        }
        else
        {
            Node* q = p->next;
            p->data = q->data;
            p->next = p->next->next;
            free(q);
            mylist->size--;
        }
        return true;
    }
    else
    {
        return false;
    }
}

void sort(List *mylist)
{
    if (mylist->size <= 1)
    {
        return;
    }
    Node *s = mylist->first->next;
    Node *q = s->next;

    mylist->last = s;
    mylist->last->next = NULL;

    while (q!=NULL)
    {
        s = q;
        q = q->next;

        Node*p = mylist->first;
        while (p->next != NULL &&p->next->data < s->data)
        {
            p = p->next;
        }

        if (p->next == NULL)   //考虑到插在最后一个节点  
        {
            mylist->last = s;
        }

        s->next = p->next;
        p->next = s;

        mylist->size++;
    }
}

void resver(List *mylist)
{
    if (mylist->size <= 1)
    {
        return;
    }

    Node *s = mylist->first->next;
    Node *q = s->next;

    mylist->last = s;
    mylist->last->next = NULL;

    while (q!=NULL)
    {
        s = q;
        q = q->next;

        s->next = mylist->first->next;
        mylist->first->next = s;

    }

    return;
}

void clear(List *mylist)
{
    if (mylist->size==0)
    {
        return;
    }

    Node *p = mylist->first->next;

    while (p!=NULL)
    {
        mylist->first->next = p->next;
        free(p);
        p = mylist->first->next;
    }

    mylist->last = mylist->first;
    mylist->size = 0;
    return;
}

void destroy(List *mylist)
{
    clear(mylist);
    free(mylist->first);
    mylist->first = mylist->last = NULL;
}

/********************************************/

Iter begin(List *list)
{
    return list->first->next;
}

Iter end(List *list)
{
    return list->last->next;
}

void insert(List *list, Iter pos, ElemType x)
{
    Node *p = list->first;
    while (p->next!=pos)
    {
        p = p->next;
    }

    Node *s = creatNode();
    s->data = x;

    s->next = p->next;
    p->next = s;

    if (pos==NULL)
    {
        list->last = s;
    }
}


----------

//main.c

#include "Slist.h"


int main()
{
    List myList;
    InitList(&myList);
    Node *p = NULL;
    int select = 1;
    while (select)
    {
        printf("**********************************************\n");
        printf("*[1]push_back                   [2]push_front*\n");
        printf("*[3]show_list                   [4]pop_back  *\n");
        printf("*[5]pop_front                   [6]insert_val*\n");
        printf("*[7]find                        [8]length    *\n");
        printf("*[9]delete_val                  [10]sort     *\n");
        printf("*[11]resver                     [12]clear    *\n");
        printf("*[13]destory                    [0]quit      *\n");
        printf("**********************************************\n");
        printf("请选择:>");
        scanf_s("%d", &select);
        switch (select)
        {
        case 1:
            int a;
            printf("请输入要插入的数据(-1结束):>");
            while (scanf_s("%d",&a))
            {
                if (a==-1)
                {
                    break;
                }
                push_back(&myList, a);
            }
            break;
        case 2:
            break;
        case 3:
            show_list(&myList);
            break;
        case 4:
            pop_back(&myList);
            break;
        case 5:
            pop_front(&myList);
            break;
        case 6:
            printf("请输入要插入的数据:>");
            scanf_s("%d", &a);
            insert_val(&myList, a);
            break;
        case 7:
            printf("请输入要查找的数据");
            scanf_s("%d", &a);
            p = find(&myList, a);
            if (p==NULL)
            {
                printf("数据不存在\n");
            }
            break;
        case 8:
            printf("单链表的长度:> %d\n", length(&myList));
            break;
        case 9:
            printf("请输入要删除的值> ");
            scanf_s("%d", &a);
            if (!delete_val(&myList, a))
            {
                printf("删除失败!");
            }
            break;
        case 10:
            sort(&myList);
            show_list(&myList);
            break;
        case 11:
            resver(&myList);
            break;
        case 12:
            clear(&myList);
        case 13:
            destroy(&myList);
        default:
            break;
        }
    }
    getchar();
    return 0;
}

我的个人网站 http://www.breeziness.cn/
我的CSDN http://blog.csdn.net/qq_33775402

转载请注明出处 小风code www.breeziness.cn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值