顺序表和链表

数据结构

顺序结构
链式结构
栈和队列
树和图(二叉树)
查找和排序(hash表

画图写代码

1.顺序表

顺序表
插入
删除
顺序表
根据画图了解顺序表的特点 :
1. 地址连续,大小固定
2. 除了第一个元素外,其它元素都有前驱。
除了最后一个元素外,其它元素都有后继。
3. 访问方便,通过下标来访问
4. 删除和插入不方便,可能需要移动元素

  • 创建顺序表、实现数据的增、删、改、查、删除表
    功能性的接口和测试分开
    list.c/list.h/test.c
    分析:
    list.h
     常量定义
     类型申明
      全局变量申明
      函数的申明
    list.c
      定义全局变量
      定义函数
    test.c
      main函数
list.h:
#ifndef _LIST_H_
#define _LIST_H_

//常量定义
#define SIZE 10

typedef enum e_result
{
	ERROR = -1,
	OK,

	FALSE = 0,
	TRUE,
}E_RESULT;

//类型声明
typedef int data_type;
typedef unsigned int uInt;
typedef struct list
{
	data_type data[SIZE];
	uInt count;
}LIST;

//函数的申明
/*
函数名:createList
函数功能:创建线性表
函数参数:无
函数返回值:成功时返回线性表的首地址,失败返回NULL.
*/
LIST * createList(void);

/*
函数名:destroyList
函数功能:销毁线性表
函数参数:LIST * pList 表示要销毁的线性表的首地址
函数返回值:无.
*/
void destroyList(LIST * pList);

/*
函数名:insertToList
函数功能:插入一个元素到线性表中
函数参数:
	LIST * pList 表示要插入的线性表的首地址
	int offset :表示要插入的位置
	data_type newItem : 表示要插入的元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int insertToList(LIST * const pList, int offset, data_type newItem);

/*
函数名:deleteFromList
函数功能:从线性表中删除一个元素
函数参数:
	LIST * pList 表示要操作的线性表的首地址
	int offset :表示要删除的位置
	data_type * pDelItem : 保存被删除的元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int deleteFromList(LIST * const pList, int offset, data_type * const pDelItem);

/*
函数名:updateList
函数功能:修改线性表中的一个元素
函数参数:
	LIST * pList 表示要操作的线性表的首地址
	int offset :表示要修改的位置
	data_type newValue : 修改后元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int updataList(LIST * const pList, int offset, data_type newValue);

/*
函数名:searchItemFormList
函数功能:从线性表中查找和指定元素相等的元素,返回第一次出现的位置
函数参数:
	LIST * pList 表示要操作的线性表的首地址
	data_type item : 被查找的元素的值
函数返回值:成功时返回下标,失败返回-1.
*/
int searchItemFormList(LIST * const pList, data_type item);

/*
函数名:showList
函数功能:显示线性表中元素的值
函数参数:
	LIST * pList 表示要显示的线性表的首地址
函数返回值:无.
*/
void showList(LIST * pList);

#endif

list.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "list.h"

/*
函数名:createList
函数功能:创建线性表
函数参数:无
函数返回值:成功时返回线性表的首地址,失败返回NULL.
*/
LIST * createList(void)
{
	LIST * pList = NULL;
	pList = (LIST *)malloc(sizeof(LIST));
	if(NULL != pList)
	{
		memset(pList, 0, sizeof(LIST));
		pList->count = 0;//表为空
	}
	return pList;
}

/*
函数名:destroyList
函数功能:销毁线性表
函数参数:LIST * pList 表示要销毁的线性表的首地址
函数返回值:无.
*/
void destroyList(LIST * pList)
{
	if(NULL == pList)
		return ;
	free(pList);
	pList = NULL;
}

/*
函数名:insertToList
函数功能:插入一个元素到线性表中
函数参数:
	LIST * pList 表示要插入的线性表的首地址
	int offset :表示要插入的位置
	data_type newItem : 表示要插入的元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int insertToList(LIST * const pList, int offset, data_type newItem)
{
	int i = 0;
	//参数判断
	if(NULL == pList || offset >pList->count || offset < 0)
	{
		printf("参数不对\r\n");
		return ERROR;
	}
	//表是否为满
	if(SIZE == pList->count)
	{
		printf("线性表满\r\n");
		return ERROR;
	}
	//移动元素
	for(i = pList->count - 1; i >= offset; i--)
	{
		pList->data[i + 1] = pList->data[i];
	}
	//插入元素
	pList->data[offset] = newItem;
	//更新计数器
	pList->count++;
	return OK;
}

/*
函数名:showList
函数功能:显示线性表中元素的值
函数参数:
	LIST * pList 表示要显示的线性表的首地址	
函数返回值:无.
*/
void showList(LIST * pList)
{
	int i = 0;

	//参数判断
	if(NULL == pList)
		return ;
	for(i = 0; i < pList->count; i++)
		printf("%d\t",pList->data[i]);
	printf("\n");
}

/*
函数名:deleteFromList
函数功能:从线性表中删除一个元素
函数参数:
	LIST * pList 表示要操作的线性表的首地址
	int offset :表示要删除的位置
	data_type * pDelItem : 保存被删除的元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int deleteFromList(LIST * const pList, int offset, data_type * const pDelItem)
{
	int i = 0;
	//判断参数
	if(NULL == pList || offset > pList->count || offset < 0)
	{
		printf("参数不对\r\n");
		return ERROR;
	}
	//保存被删除元素的值
	if(NULL != pDelItem)
	{
		*pDelItem = pList->data[offset];
	}
	//移动元素
	for(i = offset + 1; i < pList->count; i++)
	{
		pList->data[i - 1] = pList->data[i];
	}
	//更新计算器
	pList->count--;
	return OK;
}

/*
函数名:updateList
函数功能:修改线性表中的一个元素
函数参数:
	LIST * pList 表示要操作的线性表的首地址
	int offset :表示要修改的位置
	data_type newValue : 修改后元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int updataList(LIST * const pList, int offset, data_type newValue)
{
	//判断参数
	if(NULL == pList || offset > pList->count || offset < 0)
	{
		printf("参数不对\r\n");
		return ERROR;
	}
	pList->data[offset] = newValue;
	return OK;
}

/*
函数名:searchItemFormList
函数功能:从线性表中查找和指定元素相等的元素,返回第一次出现的位置
函数参数:
	LIST * pList 表示要操作的线性表的首地址
	data_type item : 被查找的元素的值
函数返回值:成功时返回下标,失败返回-1.
*/
int searchItemFormList(LIST * const pList, data_type item)
{
	int i = 0;
	//判断参数
	if(NULL == pList)
	{
		printf("参数不对\r\n");
		return ERROR;
	}
	for(i = 0; i < pList->count; i++)
	{
		if(pList->data[i] == item)
			break;
	}
	if(i == pList->count)
	{
		printf("找不到该元素\r\n");
		return ERROR;
	}
	return i;
}

//如果表满,返回1,如果表不满,返回0,如果表不存在-1;
int isFull(LIST * pList)
{
	if (NULL == pList)
		return ERROR;
	if (SIZE == pList -> count)
		return TRUE;
	return FALSE;
}

int isEmpty(LIST * pList)
{
	if (NULL == pList)
	{
		return ERROR;
	}
	if (0 == pList->count)
	{
		return TRUE;
	}
	return FALSE;
}

test.c:
#include <stdio.h>
#include "list.h"

int main(void)
{
	LIST * pList = NULL;
	data_type * pDelItem = NULL;
	data_type delData = 0;
	//创建线性表
	pList = createList();
	if(NULL == pList)
	{
		printf("线性表创建失败\r\n");
		return ERROR;
	}

	//插入数据
	insertToList(pList, 0, 1);
	insertToList(pList, 1, 3);
	insertToList(pList, 2, 5);
	insertToList(pList, 1, 4); // 1,4,3,5
	//显示
	showList(pList);

		//删除
	if (OK == deleteFromList(pList, -10, pDelItem))
	{
		if (NULL != pDelItem)
			printf("delete item =%d\r\n", *pDelItem );
	}
	//显示
	showList(pList);

	//删除
	if (OK == deleteFromList(pList, 0, &delData))
	{
		printf("delete item =%d\r\n", delData );
	}
	//显示
	showList(pList);
	updataList(pList, 2, 100);
	showList(pList);
	int m = searchItemFormList(pList, 200);
	if(m != -1)
	printf("该元素下标为%d\n",m);
	//销毁线性表
	destroyList(pList);

	return 0;
}

输出结果:
1	4	3	5	
参数不对
1	4	3	5	
delete item =1
4	3	5	
4	3	100	
找不到该元素

2.链表

单向不循环链表
概念:

  • 头结点:数据域为空
  • 首结点:头结点的下一个结点
  • 尾结点:指针域为空
  • 一般,在操作链表的时候,都是从头结点开始。

特点:

  • 地址可以不连续
  • 大小不固定
  • 访问不方便,一般要通过头结点开始向后挨个结点进行访问
  • 插入和删除方便,不需要移动元素

操作:创建表、销毁表、增、删、改、查、判空
插入

list.h:
#ifndef _LIST_H_
#define _LIT_H_

typedef enum e_result
{
    ERROR = -1, 
    OK, 
    
    FALSE = 0,
    TRUE,
}E_RESULT;

enum position
{
    TAIL = -1, 
    HEAD,
};

//类型声明
typedef int data_type;
typedef unsigned int uInt;

typedef struct list
{
    data_type data;//数据域
    struct list * pNext;//指针域
}LIST;

//函数的申明
/*
函数名:createList
函数功能:创建线性表
函数参数:无
函数返回值:成功时返回线性表的首地址,失败返回NULL.
*/
LIST * createList(void);

/*
函数名:destroyList
函数功能:销毁线性表
函数参数:LIST * pList 表示要销毁的线性表的首地址
函数返回值:无.
*/
void destroyList(LIST * pList);

/*
函数名:insertToList
函数功能:插入一个元素到线性表中
函数参数:
    LIST * pList 表示要插入的线性表的首地址
    int offset :表示要插入的位置,
        当offset=0,表示头插;当offset=-1时,尾插;首结点的编号为1,后面挨个加1.
        例:offset=5时,表示插入到第5个结点之后
    data_type newItem : 表示要插入的元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int insertToList(LIST * const pList, int offset, data_type newItem);

/*
函数名:deleteFromList
函数功能:从线性表中删除一个元素
函数参数:
    LIST * pList 表示要操作的线性表的首地址
    int offset :表示要删除的位置
    data_type * pDelItem : 保存被删除的元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int deleteFromList(LIST * const pList, int offset, data_type * const pDelItem);

/*
函数名:updateList
函数功能:修改线性表中的一个元素
函数参数:
    LIST * pList 表示要操作的线性表的首地址
    int offset :表示要修改的位置
    data_type newValue : 修改后元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int updateList(LIST * const pList, int offset, data_type newValue);


/*
函数名:searchItemFormList
函数功能:从线性表中查找和指定元素相等的元素,返回第一次出现的位置
函数参数:
    LIST * pList 表示要操作的线性表的首地址
    data_type item : 被查找的元素的值
函数返回值:成功时返回下标,失败返回-1.
*/
int searchItemFormList(LIST * const pList, data_type item);

/*
函数名:showList
函数功能:显示线性表中元素的值
函数参数:
    LIST * pList 表示要显示的线性表的首地址 
函数返回值:无.
*/
void showList(const LIST * pList);

int isEmpty(LIST * pList);

#endif


linkedList.c :
include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "list.h"

/*
函数名:createList
函数功能:创建线性表
函数参数:无
函数返回值:成功时返回线性表的首地址,失败返回NULL.
*/
LIST * createList(void)
{
    LIST * pList = NULL;
    pList = (LIST *)malloc(sizeof(LIST));
    if(NULL != pList)
    {   
        memset(pList, 0, sizeof(LIST));
    }   
    return pList;
}

/*
函数名:destroyList
函数功能:销毁线性表
函数参数:LIST * pList 表示要销毁的线性表的首地址
函数返回值:无.
*/
void destroyList(LIST * pList)
{
    LIST * pTmp;
    //判断参数
    if(NULL == pList)
        return ;
    while(1)
    {   
        //pTmp指向首结点
        pTmp = pList->pNext;
        if(NULL == pTmp)
        {
            break;
        }
        //保护pTmp后的所有结点
        pList->pNext = pTmp->pNext;
        //释放pTmp
        free(pTmp);
    }
    free(pList);
    pList = NULL;
}

/*
函数名:insertToList
函数功能:插入一个元素到线性表中
函数参数:
    LIST * pList 表示要插入的线性表的首地址
    int offset :表示要插入的位置
        当offset=0,表示头插;当offset=-1时,尾插;首结点的编号为1,后面挨个加1.
        例:offset=5时,表示插入到第5个结点之后
    data_type newItem : 表示要插入的元素的值
函数返回值:成功时返回0,失败返回-1.
int insertToList(LIST * const pList, int offset, data_type newItem)
{
    LIST * pNew = NULL;
    LIST * pTmp = NULL;
    int count = 0;
    //判断参数
    if(NULL == pList || offset < TAIL)
        return ERROR;
    //新建一个结点pNew
    pNew = (LIST *)malloc(sizeof(LIST));
    if(NULL == pNew)
    {
        printf("新建一个结点pNew失败\r\n");
        return ERROR;
    }
    memset(pNew, 0, sizeof(LIST));
    memcpy(&(pNew->data), &newItem, sizeof(data_type));//pNew->data = newItem;

    //头插法
    if(HEAD == offset)
    {
        //找到要插入的位置pTmp后面
        pTmp = pList;
        //保护pTmp后的所有结点
        pNew->pNext = pTmp->pNext;
        //pTmp指向pNew
        pTmp->pNext = pNew;
    }
    //尾插法
    else if(TAIL == offset)
    {
        //找到尾结点pTmp
        pTmp = pList;
        while(NULL != pTmp)
        {
            pTmp = pTmp->pNext;
            if(NULL == pTmp->pNext)
            {
                break;
            }
        }
        //pTmp指向pNew
        pTmp->pNext = pNew;
    }
    //中间插入
    else
    {
        //找到要插入的位置pTmp后面
        pTmp = pList;
        while(NULL != pTmp)
        {
            pTmp = pTmp->pNext;
            count++;
            if(count == offset)
            {
                break;//找到了
            }
        }
        if(NULL == pTmp)
        {
            //没找到
            free(pNew);
            pNew = NULL;
            return ERROR;
        }
        //保护pTmp后的所有结点
        pNew->pNext = pTmp->pNext;
       //pTmp指向pNew
        pTmp->pNext = pNew;
    }
    return OK;
}

/*
函数名:showList
函数功能:显示线性表中元素的值
函数参数:
    LIST * pList 表示要显示的线性表的首地址 
函数返回值:无.
*/
void showList(const LIST  * pList)
{
    const LIST * pTmp = pList;
    //参数判断
    if(NULL == pList || NULL == pList->pNext)
        return ;
    //从首结点到尾结点依次打印
    while(NULL != pTmp)
    {
        pTmp = pTmp->pNext;
        if(NULL != pTmp)
        {
            printf("%d -> ",pTmp->data);
        }
    }
    printf("^\r\n");
}

/*
函数名:deleteFromList
函数功能:从线性表中删除一个元素
函数参数:
    LIST * pList 表示要操作的线性表的首地址
    int offset :表示要删除的位置
    data_type * pDelItem : 保存被删除的元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int deleteFromList(LIST * const pList, int offset, data_type * const pDelItem)
{
    LIST * pTmp = NULL;
    LIST * pCur = NULL;
    LIST * pDel = NULL;
    pTmp = pList;
    int count = 0;
    //判断参数
    if(NULL == pList || NULL == pList->pNext || offset < TAIL)
        return ERROR;
    if(HEAD == offset)
    {
        *pDelItem = pTmp->pNext->data;
        pDel = pTmp->pNext;
        //保护后面的结点
        pTmp->pNext = pDel->pNext;
        free(pDel);
        pDel = NULL;
    }
    else if(TAIL == offset)
    {
        //找到尾结点pTmp
        while(NULL != pTmp->pNext)
        {
            pCur = pTmp;
            pTmp = pTmp->pNext;
        }
        *pDelItem = pTmp->data;
        pCur->pNext = NULL;
       pDel = pTmp;
        free(pDel);
        pDel = NULL;
    }
    else
    {
        while(NULL != pTmp)
        {
            pCur = pTmp;
            pTmp = pTmp->pNext;
            count++;

            if(count == offset)
            {
                break;
            }
        }
        if(NULL == pTmp)
        {
            printf("删除失败,没有此节点\r\n");
            return ERROR;
        }
        //找到结点
        *pDelItem = pTmp->data;
        pCur->pNext = pTmp->pNext;
        pDel = pTmp;
        free(pDel);
        pDel = NULL;
    }
/*
函数名:updateList
函数功能:修改线性表中的一个元素
函数参数:
    LIST * pList 表示要操作的线性表的首地址
    int offset :表示要修改的位置
    从offset=1开始修改;当offset=-1时,就是修改尾结点;首结点的编号为1,后面挨个加1.
    例:offset=5时,表示修改第5个结点
    data_type newValue : 修改后元素的值
函数返回值:成功时返回0,失败返回-1.
*/
int updateList(LIST * const pList, int offset, data_type newValue)
{
    LIST * pTmp = pList;
    int count = 0;
    //判断参数
    if(NULL == pList || NULL == pList->pNext || offset < TAIL)
        return ERROR;

    if(HEAD == offset)
    {
        pTmp->pNext->data = newValue;
    }
    else if(TAIL == offset)
    {
        while(NULL != pTmp)
        {
            pTmp = pTmp->pNext;
            if (NULL == pTmp->pNext)
            {
                break;
            }
        }
        pTmp->data = newValue;
    }
    else
    {
        while(NULL != pTmp)
        {
            pTmp = pTmp->pNext;
            count++;

            if(count == offset)
            {
                pTmp->data = newValue;
                break;
            }
        }
        if(NULL == pTmp)
        {
            printf("修改失败,没有此结点\r\n");
            return ERROR;
        }
    }
    return OK;
}
/*
函数名:searchItemFormList
函数功能:从线性表中查找和指定元素相等的元素,返回第一次出现的位置
函数参数:
    LIST * pList 表示要操作的线性表的首地址
    data_type item : 被查找的元素的值
函数返回值:成功时返回下标,失败返回-1.
*/
int searchItemFormList(LIST * const pList, data_type item)
{
    int count = 0;
    LIST * pTmp = pList;
    //判断参数
    if(NULL == pList || NULL == pList->pNext)
        return ERROR;

    while(NULL != pTmp)
    {
        pTmp = pTmp->pNext;
        count++;

        if(NULL != pTmp && item == pTmp->data)
        {
            break;
        }
    }
    if(NULL == pTmp)
    {
        printf("没有找到该元素\r\n");
    }
    return count;
}
int isEmpty(LIST * pList)
{
    //判断元素
    if(NULL == pList)
    {
        printf("该链表不存在\r\n");
        return ERROR;
    }
    if(NULL == pList->pNext)
    {
        printf("该链表为空\r\n");
        return TRUE;
    }
    return 0;
}


test.c:
#include <stdio.h>
#include "list.h"

int main()
{
    LIST * pList = NULL;
    data_type * pDelItem = NULL;
    data_type delData;
    //int ret = 0;
    //创建线性表
    pList = createList();
    if (NULL == pList)
    {   
        printf("线性表创建失败\r\n");
        return ERROR;
    }   
    
    int ret = isEmpty(pList);
    printf("ret = %d\r\n",ret);

    //插入数据
    insertToList(pList, 0, 1); 
    insertToList(pList, 0, 3); 
    insertToList(pList, 0, 5); 
    insertToList(pList, -1, 4); // 5314
    insertToList(pList, 3, 7); // 53174*/
    //显示
    showList(pList);
    //修改
    updateList(pList,-1,1);//5 -> 3 -> 1 -> 7 -> 1 -> ^
    showList(pList);
    updateList(pList,0,7);//7 -> 3 -> 1 -> 7 -> 1 -> ^
    showList(pList);
    updateList(pList,2,12);//7 -> 12 -> 1 -> 7 -> 1 -> ^
    showList(pList);
    
    int num = searchItemFormList(pList, 3); 
    printf("该元素的结点为%d\r\n",num);
    num = searchItemFormList(pList, 12);
    printf("该元素的结点为%d\r\n",num);
    updateList(pList,3,20);
    showList(pList);

    //删除
    if (OK == deleteFromList(pList, 0, &delData))
    {
        printf("delete item =%d\r\n", delData );
    }
    //显示
    showList(pList);//12 -> 1 -> 7 -> 1 -> ^
    //删除
    if (OK == deleteFromList(pList, -1, &delData))
    {
        printf("delete item =%d\r\n", delData );
    }
    //显示
    showList(pList);//12 -> 1 -> 7 -> 1 -> ^
    //删除
    if (OK == deleteFromList(pList, 2, &delData))
    {
        printf("delete item =%d\r\n", delData );
    }
    //显示
    showList(pList);//12 -> 1 -> 7 -> 1 -> ^

    ret = isEmpty(pList);
    printf("ret = %d",ret);
    printf("\n");
    //销毁线性表
    destroyList(pList);
    return 0;
}


运行结果:
该链表为空
ret = 1
5 -> 3 -> 1 -> 7 -> 4 -> ^
5 -> 3 -> 1 -> 7 -> 1 -> ^
7 -> 3 -> 1 -> 7 -> 1 -> ^
7 -> 12 -> 1 -> 7 -> 1 -> ^
没有找到该元素
该元素的结点为6
该元素的结点为2
7 -> 12 -> 20 -> 7 -> 1 -> ^
delete item =7
12 -> 20 -> 7 -> 1 -> ^
delete item =1
12 -> 20 -> 7 -> ^
delete item =20
12 -> 7 -> ^
ret = 0

创建空的单向链表:
创建空的单向链表
单向循环头删:
在这里插入图片描述
双向链表插入:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值