双向链表的实现

双向链表,双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
代码如下:

首先是头文件部分:

//double_link_list.h头文件
#ifndef __DOUBLE_LINK_LIST_H__
#define __DOUBLE_LINK_LIST_H__
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct Double
{
    int data;
    struct Double *prior;
    struct Double *pnext;
}NODE, *PNODE;


PNODE create(PNODE phead);

void traverse_list(PNODE phead);

int is_empty(PNODE pHead);

int lenght_list(PNODE pHead);

int insert_list(PNODE pHead, int n, int val);

int delete_list(PNODE pHead, int n, int *pVal);

int*  find(PNODE pHead, int a, int *sv);

void soert_list(PNODE pHead, char ch);

void Clear_list(PNODE phead);

PNODE DestroyList(PNODE pHead);

#endif // __DOUBLE_LINK_LIST_H__


接下来是函数文件:

//double_link_list.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"double_link_list.h"


//创建链表
PNODE create(PNODE phead)
{
    PNODE p = NULL;
    int len = 0;
    int val = 0;
    phead = (PNODE)malloc(sizeof(NODE));
    assert(phead);
    phead->prior = phead;
    phead->pnext = phead;
    p = phead;
    printf("请输入你所要创建双向链表节点的个数:");
    scanf("%d", &len);
    for (int i = 0; i < len; i++)
    {
        PNODE pnew = (PNODE)malloc(sizeof(NODE));
        assert(pnew);
        printf("输入在第%d节点的值", i + 1);
        scanf("%d", &val);

        pnew->data = val;
        p->pnext = pnew;
        pnew->prior = p;
        pnew->pnext = phead;
        phead->prior = pnew;
        p = pnew;   
    }
    return phead;
}


//遍历整个双向链表
void traverse_list(PNODE phead)
{
    assert(phead);
    PNODE p = phead->pnext;
    while (p != phead)
    {
        printf("%d ", p->data);
        p = p->pnext;
    }
    printf("\n");
}


//判断链表是否为空
int is_empty(PNODE pHead)
{
    if (pHead == pHead->pnext)
    {
        return 1;
    }

    return 0;
}


//求链表的长度
int lenght_list(PNODE pHead)
{
    int len = 0;
    assert(pHead);
    PNODE p = pHead->pnext;
    while (p)
    {
        if (p != pHead)
        {
            len++;
            p = p->pnext;
        }
        else
            break;
    }
    return len;
}


//插入在某个位置插入数据
int insert_list(PNODE pHead, int n, int val)
{
    assert(pHead);
    PNODE p = pHead ;
    int i = 0;
    //在这里进行的是寻找咱们所需要插入的那个节点
    while (NULL != p&&i < n - 1)
    {
        p = p->pnext;
        i++;
    }

    if (n <= 0 || n>lenght_list(pHead))
    {
        return 0;
    }
    PNODE pNew = (PNODE)malloc(sizeof(NODE));
    assert(pNew);
    pNew->data = val;
    pNew->prior = p;
    pNew->pnext = p->pnext;
    p->pnext->prior = pNew;
    p->pnext = pNew;
    if (p == pHead)
        pHead = pNew;
    return 1;
}



//删除指定位置节点
int delete_list(PNODE pHead, int n, int *pVal)
{
    assert(pHead);
    PNODE p = pHead;
    int i = 0;
    while (i<n)
    {
        p = p->pnext;
        i++;
    }
    if (n <= 0 || n>lenght_list(pHead))
    {
        return 0;
    }

    *pVal = p->data;
    //输出p节点后的节点,这里要注意的是一定要记得free;
    p->prior->pnext = p->pnext;

    p->pnext->prior = p->prior;
    if (pHead == p)
        pHead = p;
    free(p);
    return 1;
}



//查找某个元素的位置
int*  find(PNODE pHead, int a, int *sv)
{
    assert(pHead);
    int count = 1;
    PNODE p = pHead->pnext;
    while (p != pHead)
    {
        p = p->pnext;
        count++;
        if (a == p->data)
        {
            *sv = count;
            return sv;
        }
    }
    return NULL;
}




//链表排序
//链表排序最适合的是冒泡排序法。
void soert_list(PNODE pHead, char ch)
{
    assert(pHead);
    if ('>' == ch)
    {
        for (PNODE p1 = pHead->pnext; p1 != pHead; p1 = p1->pnext)
        {
            for (PNODE p2 = pHead->pnext; p2 != pHead; p2 = p2->pnext)
            {
                if ((p1->data) > (p2->data))
                {
                    int tmp = p1->data;
                    p1->data = p2->data;
                    p2->data = tmp;
                }
            }
        }
    }
    else if ('<' == ch)
    {
        for (PNODE p1 = pHead->pnext; p1 != pHead; p1 = p1->pnext)
        {
            for (PNODE p2 = pHead->pnext; p2 != pHead; p2 = p2->pnext)
            {
                if ((p1->data) < (p2->data))
                {
                    int tmp = p1->data;
                    p1->data = p2->data;
                    p2->data = tmp;
                }
            }
        }
    }
}





//销毁链表
PNODE DestroyList(PNODE pHead)
{
    PNODE q, p;
    assert(pHead);
    p = q = NULL;
    p = pHead;
    while (p->pnext != pHead)
    {
        q = p->pnext;//让q指向下一个节点
        p->pnext = q->pnext;//p存储了q。下一个节点的地址;
        free(q);
    }
    free(pHead);
    return NULL;
}


最后是测试函数部分:

#define _CRT_SECURE_NO_WARNINGS 1
#include"double_link_list.h"
int main()
{
    PNODE phead = NULL;
    int len = 0;

    //测试创建双向链表
    phead=create(phead);


    //测试遍历双向链表
    traverse_list(phead);


    //测试双向链表是否为空
    if (is_empty(phead) == 1)
        printf("这个链表为空\n");
    else
        printf("这个链表不为空\n");


    //测试求循环链表的长度
    printf("此双向链表的长度为:\n");
    len = lenght_list(phead);
    printf("%d\n", len);


    //测试双向插入在某个位置插入数据
    int n = 0;
    int val = 0;
    printf("请输入你所需要插入的位置:");
    scanf("%d", &n);
    printf("请输入你所需要插入的数据:");
    scanf("%d", &val);
    if (insert_list(phead, n, val) == 0)
        printf("插入失败\n");
    else
        printf("插入成功\n");
    traverse_list(phead);


    //测试双向链表删除指定位置的节点
    int del_Val = 0;
    printf("请输入你所需要删除的节点所在的位置:");
    scanf("%d", &n);
    if (delete_list(phead, n, &del_Val))
    {

        printf("删除元素%d成功\n", del_Val);
    }
    else
    {
        printf("删除元素%d失败\n", del_Val);
    }
    traverse_list(phead);


    //测试双向链表元素查找,并且返回所在位置
    int a = 0;
    int find_position = 0;
    printf("输入你所要查找的元素");
    scanf("%d", &a);
    if (find(phead, a, &find_position) == NULL)
        printf("该双向链表中没有这一个元素。\n");
    else
    {
        printf("所查找的元素位置位于:\n");
        printf("%d\n", find_position);
    }


    //测试双向链表的排序
    char ch = 0;
    printf("选择双向链表的排序方式(输入'>'(降序)或者'<'(升序)):\n");
    fflush(stdin);
    scanf("%c", &ch);
    soert_list(phead, ch);
    traverse_list(phead);


    //测试销毁链表
    phead = DestroyList(phead);


    system("pause");
    return 0;
}

小白一枚,希望大家多多指教。

你可能感兴趣的:(双向链表的实现)