c语言实现企业链表

c语言实现企业链表

我们最早学习的线性表分为顺序表和链表,顺序表即用数组来模拟链表,他的内存是连续的;缺点在于事先要知道大小,但是实际生活中我们并不能实现准确的预知对象有多大,需要多少内存。因此就诞生了链式存储的顺序表,即链表;链表也是分为三种,传统链表、内核链表,和企业链表。那么这三种链表分别有什么特点呢?
(1)传统链表:传统链表区别于数组模拟的线性表,可以不用管到底需要多大的内存,比较方便。第二个特点是他的内存不是连续的,每个结点包含一个数据域和指针域。每个节点的指针域保存的是下一个节点的地址。他的缺点在于,如果节点的成员变量发生改变(新增或者删除)那么整个程序都要随之改变。
(2)内核链表:内核链表全名为linux内核链表,由linux之父linus(托瓦尔兹)发明。发明这个链表的原因是基于以上的问题,传统链表不能包含世间万物,那索性他就不包含了,反过来让世间万物包含我,是不是很有哲学思想。他的缺点在于,指针节点在结构体内有一个地址偏移量
(3)企业链表:基于上面的问题,内核链表的指针成员变量有一个偏移量,那么企业链表的改变在于,将指针成员变量前移至第一个成员变量,这样整个结构体的内存地址和第一个成员变量(即指针成员变量)就重合了,解决了地址偏移量的 问题;他们的技术推演路线图如下:
链表体系的技术推演
我们平时用的就是传统链表和企业链表。下面我们来看这两种链表用C/C++的实现方式:

//传统链表
// 数据结构.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
using namespace std;
typedef struct node
{
    int data;
    node* next;
}Slist;
Slist* creatlist();
int printSlist(Slist* phead);
int delnode(Slist*, int x);
int insertnode(Slist*, int x, int y);
int destroynode(Slist*);
int main()
{
    //Slist* phead, * PM, Pcur;
    Slist* phead;
    phead=creatlist();
    cout << "           " << endl;
    printSlist(phead);
    insertnode(phead, 20, 19);
    printSlist(phead);
    delnode(phead, 19);
    printSlist(phead);
    destroynode(phead);
    printSlist(phead);

    std::cout << "Hello World!\n";
}

Slist* creatlist()
{
    int x;
    Slist* Phead, *PM, *Pcur;
    Phead = (Slist*)malloc(sizeof(Slist));
    if (Phead == NULL)
    {
        return NULL;
    }
    else
    {
        Phead->data = 0;
        Phead->next = NULL;
    }
    cout << "please inter your data" << endl;
    cin >> x;
    Pcur = Phead;

    while (x!= -1)
    {
        PM = (Slist*)malloc(sizeof(Slist));
        if (PM == NULL)
        {
            return NULL;
        }
        else
        {

            PM->data = x;
            PM->next = NULL;
            Pcur->next = PM; 
            Pcur = PM;
            cin >> x;
        }
    }
    return Phead;
}

int printSlist(Slist* phead)
{
    Slist* tmp;
    if (phead == NULL)
    {
        return -1;
    }
    tmp = phead->next;
    while (tmp)
    {
        cout << tmp->data<<" ";
        tmp = tmp->next; 
    }
    return 0;
    
}

//单项链表的位置保存在前驱节点的next中
int insertnode(Slist* Phead, int x, int y)
{
    Slist * pPre, * pM, * pCur;
    pM = (Slist*)malloc(sizeof(Slist));
    if (pM == NULL)
        return -1;
    pPre = Phead;
    pCur = pPre-> next;
    while (pCur)
    {
        if (pCur->data == x)
        {
            pM->data = y;
            pM->next = pCur;
            pPre->next = pM;
        }
        pPre = pCur;
        pCur = pCur->next;
    }
    return 0;
}

int delnode(Slist* phead, int x)
{
    Slist* pPre, *pCur;
    pPre = phead;
    pCur = phead->next;
    while (pCur)
    {
        if (pCur->data == x)
        {
            //pPre->next = pCur->next;
            //free(pCur);释放内存之后得到不能再用pCur;所以pPre可能是一个野指针;导致程序崩溃;
            break;
        }
        pPre = pCur;
        pCur = pCur->next;
    }
    if (pCur == NULL)
    {
        cout << "没找到节点" << endl;
        return -1;
    }
    pPre->next = pCur->next;
    free(pCur);
    
    return 0;
}

int destroynode(Slist* phead)
{
    Slist* tmp = NULL;
    if (phead == NULL)
        return -1;
    while(phead)
    {
        tmp = phead->next;
        free(phead);
        phead = tmp;
    }
    return 0;
}

//上面部分是传统链表的一些基本操作;下面我们来看企业链表的一些api函数;
//企业链表,企业链表我们将业务结点和算法分开实现;
//定义一个企业链表的头文件,将结点的定义和api函数的实现全部包含进来
//LinK_List.h
#ifndef _MYLINKLIST_H_
#define _MYLINKLIST_H_
typedef void LinkList;
typedef struct _tag_LinkListNode
{
	struct _tag_LinkListNode* next;
}LinkListNode;//定义一个结点,后面讲这个结点包含进去业务节点,然后将这个结点连起来,所有的业务结点就自然而然的连起来了;
LinkList* LinkList_Creat();
void LinkList_Destroy(LinkList* list);
void LinkList_Clear(LinkList* list);
int LinkList_Length(LinkList* list);
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
LinkListNode* LinkList_Get(LinkList* list, int pos);
LinkListNode* LinkList_Delete(LinkList* list, int pos);
#endif
//链表及其基本api函数的底层实现
//Link_List.cpp
#include<iostream>
#include"LinkList.h"
using namespace std;
typedef struct _tag_LinkList
{
	LinkListNode header;
	int length;
}TLinkList;
LinkList* LinkList_Creat()
{
	TLinkList* tmp = NULL;
	tmp = (TLinkList*)malloc(sizeof(TLinkList));
	if (tmp == NULL)
	{
		cout << "LinkList_Create() error" << endl;
		return NULL;
	} 
	memset(tmp, 0, sizeof(TLinkList)); 
	return tmp;
}
void LinkList_Destroy(LinkList* list)
{
	if (list == NULL)
	{
		return;
	}
	free(list);
	return;
}
void LinkList_Clear(LinkList* list)
{
	TLinkList* tlist = NULL;
	tlist = (TLinkList*)list;
	if (tlist == NULL)
	{
		return;
	}
	tlist->header.next = NULL;
	tlist->length = 0;
	return;
}
int LinkList_Length(LinkList* list)
{
	TLinkList* tlist = NULL;
	tlist = (TLinkList*)list;
	if (tlist == NULL)
	{
		return -1;
	}
	return tlist->length;
}
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)
{
	int i = 0;
	LinkListNode *pcur=NULL;
	TLinkList* tList = NULL;
	tList = (TLinkList*)list;
	pcur = &(tList->header);
	if (list == NULL || node == NULL || pos < 0)
	{
		return -1;
	}
	for (i = 0; i < pos; i++)
	{
		pcur = pcur->next;
	}
	node->next = pcur->next;
	pcur->next = node;
	tList->length++;
	return 0;
}
LinkListNode* LinkList_Get(LinkList* list, int pos)
{
	int i = 0;
	LinkListNode* pcur = NULL;
	TLinkList* tList = NULL;
	tList = (TLinkList*)list;
	pcur = &(tList->header);
	if (list == NULL ||  pos < 0)
	{
		return NULL;
	}
	for (i = 0; i < pos; i++)
	{
		pcur = pcur->next;
	}
	return pcur->next;
}
LinkListNode* LinkList_Delete(LinkList* list, int pos)
{
	int i = 0;
	LinkListNode* pcur = NULL;
	LinkListNode* ret = NULL;
	TLinkList* tlist=NULL;
	tlist = (TLinkList*)list;
	pcur = &(tlist->header);
	if (list == NULL || pos < 0)
	{
		return NULL;
	}
	for (i = 0; i < pos; i++)
	{
		pcur = pcur->next;
	}
	ret=pcur->next;
	pcur->next = ret->next;
	tlist->length--;
	//free(ret);
	return ret;
}

//上层测试函数
//链表框架搭建及实现.cpp
#include<iostream>
#include"LinkList.h"
using namespace std;
//思考1:业务节点和链表算法是如何分离的
//思考2:业务节点的生命周期归测试程序管;

typedef struct _Teacher//业务节点
{
	LinkListNode node;
	char  name[32];
	int age;
}Teacher;
void main()
{
	Teacher t1, t2, t3,t4,t5,t6;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;
	t4.age = 34;
	t5.age = 35;
	t6.age = 36;
	LinkList* list = NULL;
	list = LinkList_Creat();
	//插入元素
	LinkList_Insert(list, (LinkListNode*)(&t1), 0);
	LinkList_Insert(list, (LinkListNode*)(&t2), 0);
	LinkList_Insert(list, (LinkListNode*)(&t3), 0);
	LinkList_Insert(list, (LinkListNode*)(&t4), 0);
	LinkList_Insert(list, (LinkListNode*)(&t5), 0);
	LinkList_Insert(list, (LinkListNode*)(&t6), 3);
	
	//遍历链表
	for (int i = 0; i<LinkList_Length(list); i++)
	{
		Teacher* tmp = (Teacher*)LinkList_Get(list, i);
		if (tmp == NULL)
			return;
		cout << tmp->age << endl;

	}
	//删除链表;
	while (LinkList_Length(list) > 0)
	{
		Teacher* tmp = (Teacher*)LinkList_Delete(list, 0);
		if (tmp == NULL)
			return;
		cout << tmp->age << endl;
	}
	LinkList_Destroy(list);
	return ;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值