C++ 数据结构 线性链表

  • #pragma once 减少头文件组合,降低编译出错的概率
  • 作用等效于 
#ifndef FUNC_H
#define FUNC_H


代码主体


#endif

线性表的定义

  • 排队问题 
  • 简单的线性表 (物理 或者逻辑结构)
  • 1,数组
  • 2,链表

  • 线性表相关操作:
  • 1,线性表初始化
  • 2,线性表遍历
  • 3,线性表插入元素
  • 4,线性表删除元素

代码

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

#define KSIZE 10
#define FALSE 0
#define TRUE 1

/************************************************************************/
/* 线性表(linear list)
线性表是一个相当灵活的数据结构,它的长度可以根据需要增长和缩短,即对线性表的数据元素不仅可以进行访问,还可以进行插入和删除等。
抽象定义的线性表如下:
ADT:Abstract Data Type 抽象数据类型

ADT LIST

L:LIST简称,即线性表本身
i:索引
e:element简称,即元素
cur_:current简称,即当前元素
pre_:previous简称,即前一个元素
next_:next,即下一个元素
visit:对元素访问的方式

InitList(&L)                  :初始化线性表
DestroyList(&L)               :销毁线性表
ClearList(&L)                 :清空线性表
ListEmpty(L)                  :线性表是否为空
ListLength(L)                 :线性表中元素个数
GetElem(L, i, &e)             :获取线性表中指定的元素
LocateElem(L, e, compare())   :给定元素获取第一次出现的索引位置
PriorElem(L, cur_ e, &pre_ e) :给定元素获取其前一个元素
NextElem(L, cur_ e, &next_ e) :给定元素获取其后一个元素
ListInsert(&L, i, e)          :将元素插入链表中指定位置
ListDelete(&L, i, &e)         :从链表中指定位置删除元素
ListTraverse(L, visit())      :遍历元素

简单线性表--C语言实现

	线性表组成类型:int数组*/

/************************************************************************/
/*---------------------------------------
InitList(&L);
DestroyList(&L);
ClearList(&L);
ListEmpty(L);
ListLength(L);
GetElem(L, i, &e);
LocateElem(L, e, compare());
ListInsert(&L, i, e);
ListDelete(&L, i, &e);
ListTraverse(L, visit());


PriorElem(L, cur_ e, &pre_ e);
NextElem(L, cur_ e, &next_ e);
-----------------------------------------*/


int count;

void InitList(int *list);
void DestroyList(int *list);
void ClearList(int *list);
int ListEmpty(int *list);
int ListLength(int *list);
int GetElem(int *list, int i, int *e);
int LocateElem(int *list, int e);
int ListInsert(int *list, int i, int e);
int ListDelete(int *list, int i, int *e);
void ListTraverse(int *list);

int main(void)
{
	int arr[KSIZE];
	int e = 0;

	InitList(arr);
	ListInsert(arr, 0, 5);
	ListInsert(arr, 0, 8);
	ListInsert(arr, 1, 7);
	ListTraverse(arr);
	ListDelete(arr, 0, NULL);
	ListTraverse(arr);
	

	GetElem(arr, 1, &e);
	printf("e = %d\n", e);

	printf("5的索引是%d\n", LocateElem(arr, 5));

	ClearList(arr);

	if(ListEmpty(arr))
	{
		printf("线性表为空\n");
	}
	else
	{
		printf("线性表不为空\n");
	}

	printf("线性表的长度为%d\n", ListLength(arr));
	DestroyList(arr);
	
	system("pause");
	return 0;
}

void InitList(int *list)
{
	int i = 0;
	count = 0;
	for(i = 0; i < KSIZE; i++)
	{
		list[i] = 0;
	}
}

void DestroyList(int *list)
{}

void ClearList(int *list)
{
	int i = 0;
	count = 0;
	for(i = 0; i < KSIZE; i++)
	{
		list[i] = 0;
	}
}

int ListEmpty(int *list)
{
	if(count == 0)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

int ListLength(int *list)
{
	return count;
}

int GetElem(int *list, int i, int *e)
{
	if(i < count && i >= 0)
	{
		*e = list[i];
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

int LocateElem(int *list, int e)
{
	int i = 0;
	for(i = 0; i < count; i++)
	{
		if(list[i] == e)
		{
			return i;
		}
	}

	return -1;
}

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

   -------------------------
   | 0 | 1 | 2 | 3 | 4 |   |
   -------------------------
*/
/************************************************************************/
int ListInsert(int *list, int i, int e)
{
	if(i <= count && i >= 0)
	{
		/*int tempArr[KSIZE] = {0};
		int k = 0;
		int j = 0;
		int m = 0;
		for(k = 0; k < i; k++)
		{
			tempArr[j++] = list[k];
		}
		tempArr[i] = e;
		j++;
		for(k = i; k < count ; k++)
		{
			tempArr[j++] = list[k];
		}

		count++;
		for(m = 0; m < count; m++)
		{
			list[m] = tempArr[m];
		}*/

		int k = 0;
		for(k = count-1; k >= i; k--)
		{
			list[k+1] = list[k];
		}
		list[i] = e;
		count++;
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

int ListDelete(int *list, int i, int *e)
{
	if(i < count && i >= 0)
	{
		int k = 0;
		if(e != NULL)
		{
			*e = list[i];
		}
		
		for(k = i; k < count - 1; k++)
		{
			list[k] = list[k+1];
		}
		count--;
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void ListTraverse(int *list)
{
	int i = 0;
	for(i = 0; i < count; i++)
	{
		printf("%d ", list[i]);
	}
	printf("\n");
}

堆申请内存

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

#define KSIZE 10
#define FALSE 0
#define TRUE 1

/************************************************************************/
/* 线性表(linear list)
线性表是一个相当灵活的数据结构,它的长度可以根据需要增长和缩短,即对线性表的数据元素不仅可以进行访问,还可以进行插入和删除等。
抽象定义的线性表如下:
ADT:Abstract Data Type 抽象数据类型

ADT LIST

L:LIST简称,即线性表本身
i:索引
e:element简称,即元素
cur_:current简称,即当前元素
pre_:previous简称,即前一个元素
next_:next,即下一个元素
visit:对元素访问的方式

InitList(&L)                  :初始化线性表
DestroyList(&L)               :销毁线性表
ClearList(&L)                 :清空线性表
ListEmpty(L)                  :线性表是否为空
ListLength(L)                 :线性表中元素个数
GetElem(L, i, &e)             :获取线性表中指定的元素
LocateElem(L, e, compare())   :给定元素获取第一次出现的索引位置
PriorElem(L, cur_ e, &pre_ e) :给定元素获取其前一个元素
NextElem(L, cur_ e, &next_ e) :给定元素获取其后一个元素
ListInsert(&L, i, e)          :将元素插入链表中指定位置
ListDelete(&L, i, &e)         :从链表中指定位置删除元素
ListTraverse(L, visit())      :遍历元素

简单线性表--C语言实现

	线性表组成类型:int数组*/

/************************************************************************/
/*---------------------------------------
InitList(&L);
DestroyList(&L);
ClearList(&L);
ListEmpty(L);
ListLength(L);
GetElem(L, i, &e);
LocateElem(L, e, compare());
ListInsert(&L, i, e);
ListDelete(&L, i, &e);
ListTraverse(L, visit());


PriorElem(L, cur_ e, &pre_ e);
NextElem(L, cur_ e, &next_ e);
-----------------------------------------*/


int count{};
int size{};//分配的内存空间

void InitList(int *list);
void DestroyList(int *list);
void ClearList(int *list);
int ListEmpty(int *list);
int ListLength(int *list);
int GetElem(int *list, int i, int *e);
int LocateElem(int *list, int e);
int ListInsert(int *list, int i, int e);
int ListDelete(int *list, int i, int *e);
void ListTraverse(int *list);

int main(void)
{
    int arr[KSIZE];
    int e = 0;

    InitList(arr);
    ListInsert(arr, 0, 5);
    ListInsert(arr, 0, 8);
    ListInsert(arr, 1, 7);
    ListTraverse(arr);
    ListDelete(arr, 0, NULL);
    ListTraverse(arr);


    GetElem(arr, 1, &e);
    printf("e = %d\n", e);

    printf("5的索引是%d\n", LocateElem(arr, 5));

    ClearList(arr);

    if(ListEmpty(arr))
    {
        printf("线性表为空\n");
    }
    else
    {
        printf("线性表不为空\n");
    }

    printf("线性表的长度为%d\n", ListLength(arr));
    DestroyList(arr);

    system("pause");
    return 0;
}

void InitList(int *list)
{
    int i = 0;
    count = 0;
    size = KSIZE;
    //在堆上申请内存
    list = reinterpret_cast<int *>(malloc(sizeof (int) * KSIZE));
    if (list == nullptr){
        return ;
    }
    for(i = 0; i < KSIZE; i++)
    {
        list[i] = 0;
    }
}

void DestroyList(int *list)
{
    free(list);
    list = nullptr;
}

void ClearList(int *list)
{
    int i = 0;
    count = 0;
    for(i = 0; i < KSIZE; i++)
    {
        list[i] = 0;
    }
}

int ListEmpty(int *list)
{
    if(count == 0)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

int ListLength(int *list)
{
    return count;
}

int GetElem(int *list, int i, int *e)
{
    if(i < count && i >= 0)
    {
        *e = list[i];
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

int LocateElem(int *list, int e)
{
    int i = 0;
    for(i = 0; i < count; i++)
    {
        if(list[i] == e)
        {
            return i;
        }
    }

    return -1;
}

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

   -------------------------
   | 0 | 1 | 2 | 3 | 4 |   |
   -------------------------
*/
/************************************************************************/
int ListInsert(int *list, int i, int e)
{
    if(i <= count && i >= 0)
    {
        int k = 0;
        if (count == size){
            size = 2 * count;
            list = static_cast<int *>(realloc(list, size));
        }
        if (list == nullptr){
            return FALSE;
        }
        for(k = count-1; k >= i; k--)
        {
            list[k+1] = list[k];
        }
        list[i] = e;
        count++;
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

int ListDelete(int *list, int i, int *e)
{
    if(i < count && i >= 0)
    {
        int k = 0;
        if(e != NULL)
        {
            *e = list[i];
        }

        for(k = i; k < count - 1; k++)
        {
            list[k] = list[k+1];
        }
        count--;
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

void ListTraverse(int *list)
{
    int i = 0;
    for(i = 0; i < count; i++)
    {
        printf("%d ", list[i]);
    }
    printf("\n");
}

单链表

代码

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

/************************************************************************/
/* 要求:
      定义一个结构体Node,结构体由两个整数组成,
	  第一个是val,第二个是next
	  定义一个Node类型的数组,数组有3个Node节点,
	  3个Node节点的关系如下:
	  nodeA(5, 2)  nodeB(7, -1)  nodeC(8, 1)
	  数组首元素nodeA为头结点,
	  编写函数ListTraverse遍历此链表
       */
/************************************************************************/

typedef struct tagNode
{
	int val;
	int next;
}Node;

void ListTraverse(Node *pList);

int main(void)
{
	Node list[3] = {
		{5,2},
		{7,-1},
		{8,1}
	};
	ListTraverse(list);
	
	system("pause");
	return 0;
}

void ListTraverse(Node *pList)
{
	int i = 0;
	Node *pCurrentNode = &pList[i];
	while(pCurrentNode->next != -1)
	{
		printf("%d  ", pCurrentNode->val);
		i = pCurrentNode->next;
		pCurrentNode = &pList[i];
	}
	printf("%d  \n", pCurrentNode->val);
}

链表

/************************************************************************/
/* by 袁春旭                                                                  */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/************************************************************************/
/* 要求:
     编写一个单链表,每个节点就是一条信息,每条信息包含的内容如下:
	 姓名:name
	 联系方式:phone

     要求编写的函数如下:
	 InitList(Node *pHead)                               :初始化单链表*
	 DestroyList(Node *pHead)                            :销毁单链表*
	 ClearList(Node *pHead)                              :清空单链表
	 ListEmpty(Node *pHead)                              :判断单链表是否为空
	 ListLength(Node *pHead)                             :获取单链表中节点个数
	 GetElem(Node *pHead, int index, Node *pElem)        :获取单链表中指定的节点
	 LocateElem(Node *pHead, Node *pElem)                :给定节点获取单链表中第一次出现的索引位置
	 ListInsert(Node *pHead, int index, Node *pElem)     :将节点插入单链表中指定位置*
	 ListDelete(Node *pHead, int index, Node *pElem)     :从单链表中指定位置删除节点*
	 ListTraverse(Node *pHead)                           :遍历单链表中所有节点*

   作业:
     PriorElem(Node *pHead, Node *pCurElem, Node *pPreElem)  :获取给定节点的前一个节点
     NextElem(Node *pHead, Node *pCurElem, Node *pNextElem)  :获取给定节点的后一个节点



   打造自己的通讯录
     1. 设计通讯录菜单(如:插入信息,查找信息)
	 2. 扩展节点信息
	 3. 回顾文件读写知识

   提示:
     1. 使用记事本保存信息
	 2. 编写函数将信息从文件中逐一读出并按条写入链表节点
	 3. 编写函数将链表各个节点逐一写入文件,达到保存的目的
	 4. 注意读写函数的调用时机:
	       在程序运行之初加载文件。
		   在用户执行退出菜单时保存文件。
*/
/************************************************************************/

#define KLen 30

int g_iCount = 0;

typedef struct tagNode
{
	char name[KLen];
	char phone[KLen];

	struct tagNode *pNext;
}Node;

int InitList(Node **pHead);
void ClearList(Node *pHead);
void DestroyList(Node *pHead);
int ListEmpty(Node *pHead);
int ListLength(Node *pHead);
void ListTraverse(Node *pHead);
int GetElem(Node *pHead, int index, Node *pElem);
int LocateElem(Node *pHead, Node *pElem);
int ListInsert(Node *pHead, int index, Node *pElem);
int ListDelete(Node *pHead, int index, Node *pElem);

int main(void)
{
	//单元测试
	Node *pList = NULL;
	Node node1 = {"Jim", "1234", NULL};
	Node node2 = {"Merry", "4321", NULL};
	Node node3 = {"James", "3456", NULL};
	Node node4;
	InitList(&pList);
	
	ListInsert(pList, 0, &node1);
	printf("%d \n", ListLength(pList));
	ListInsert(pList, 1, &node2);
	ListInsert(pList, 1, &node3);
	printf("%d \n", ListEmpty(pList));
	printf("%d \n", ListLength(pList));
	ListTraverse(pList);

	ListDelete(pList, 2, NULL);
	printf("%d \n", ListLength(pList));
	ListTraverse(pList);

	DestroyList(pList);
	
	system("pause");
	return 0;
}

int InitList(Node **pHead)
{
	*pHead = (Node *)malloc(sizeof(Node));
	if(*pHead == NULL)
	{
		return 0;
	}
	(*pHead)->pNext = NULL;
	return 1;
}

void ClearList(Node *pHead)
{
	Node *pCurrentNode = NULL;
	Node *pNextNode = NULL;
	if(pHead->pNext != NULL)
	{
		pCurrentNode = pHead->pNext;
		while(pCurrentNode != NULL)
		{
			pNextNode = pCurrentNode->pNext;
			free(pCurrentNode);
			pCurrentNode = pNextNode;
		}
	}
}

void DestroyList(Node *pHead)
{
	ClearList(pHead);
	free(pHead);
	pHead = NULL;
}

int ListEmpty(Node *pHead)
{
	/*if(pHead->pNext == NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}*/

	if(g_iCount == 0)
	{
		return 1;
	}
	return 0;
}

int ListLength(Node *pHead)
{
	//int count = 0;
	//Node *pCurrentNode = pHead->pNext;
	//while(pCurrentNode != NULL)
	//{
	//	count++;
	//	//printf("姓名:%s   ", pCurrentNode->name);
	//	//printf("电话:%s   ", pCurrentNode->phone);
	//	pCurrentNode = pCurrentNode->pNext;
	//}
	//return count;
	return g_iCount;
}

void ListTraverse(Node *pHead)
{
	Node *pCurrentNode = pHead->pNext;
	while(pCurrentNode != NULL)
	{
		printf("姓名:%s   ", pCurrentNode->name);
		printf("电话:%s   ", pCurrentNode->phone);
		printf("\n");
		pCurrentNode = pCurrentNode->pNext;
	}
	printf("\n\n");
}

int GetElem(Node *pHead, int index, Node *pElem)
{
	int count = 0;
	if(index < 0 || index > g_iCount)
	{
		return 0;
	}
	Node *pCurrentNode = pHead;
	while(pCurrentNode != NULL)
	{
		if(count == index)
		{
			pElem = pCurrentNode;
			return 1;
		}
		count++;
		pCurrentNode = pCurrentNode->pNext;
	}
	return 1;
}

int LocateElem(Node *pHead, Node *pElem)
{
	int index = 1;
	Node *pCurrentNode = pHead->pNext;
	while(pCurrentNode != NULL)
	{
		if(!strcmp(pCurrentNode->name, pElem->name)&& !strcmp(pCurrentNode->phone, pElem->phone))
		{
			return index;
		}
		pCurrentNode = pCurrentNode->pNext;
		index++;
	}

	return -1;
}

int ListInsert(Node *pHead, int index, Node *pElem)
{
	int count = 0;
	Node *pNode = NULL;
	Node *pCurrentNode = NULL;
	if(index < 0 || index > g_iCount)
	{
		return 0;
	}
	pNode = (Node *)malloc(sizeof(Node));
	if(pNode == NULL)
	{
		return 0;
	}
	strcpy(pNode->name, pElem->name);
	strcpy(pNode->phone, pElem->phone);

	pCurrentNode = pHead;
	while(pCurrentNode != NULL)
	{
		if(count == index)
		{
			//1. 将当前节点的next指针保存
			Node *pTemp = pCurrentNode->pNext;
			//2. 让当前节点的next指针指向申请的内存
			pCurrentNode->pNext = pNode;
			//3. 将保存的next指针赋值给新节点的next指针
			pNode->pNext = pTemp;
			g_iCount++;
			return 1;
		}
		count++;
		pCurrentNode = pCurrentNode->pNext;
	}
	return 1;
}

int ListDelete(Node *pHead, int index, Node *pElem)
{
	int count = 0;
	Node *pCurrentNode = pHead;
	Node *pPreNode = NULL;
	if(index <= 0 || index > g_iCount)
	{
		return 0;
	}

	
	while(pCurrentNode != NULL)
	{
		if(count == index)
		{
			
			//1. 使currentNode的上一个节点指向currentNode的下一个节点
			pPreNode->pNext = pCurrentNode->pNext;
		
			if(pElem != NULL)
			{
				//将要删除的节点数据拷贝出来
				strcpy(pElem->name, pCurrentNode->name);
				strcpy(pElem->phone, pCurrentNode->phone);
			}
			

			//2. 删除currentNode指向的节点
			free(pCurrentNode);
			g_iCount--;
			return 1;
		}
		count++;
		pPreNode = pCurrentNode;
		pCurrentNode = pCurrentNode->pNext;
	}
	return 1;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值