数据结构:线性表、链表(顺序存储结构&链式存储结构)-C&Java实现

3 篇文章 0 订阅
2 篇文章 0 订阅

线性表(顺序存储结构)

SQList.c

/**
 * 数据结构:
 * 线性表顺序存储结构定义和其基本方法
 * 
 * @author TagBug
 * @date 2021.09.15 08:31:54
 */
#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define LIST_INIT_SIZE 100
#define LIST_INCREMENT 10

typedef unsigned short Bool;
typedef int Elemtype;
typedef struct
{
    Elemtype *data;
    int length;
    int listSize;
} SQList;

/**
 * 线性表初始化方法 
 * 清空数据数组(如果存在),并以默认初始化大小分配数据数组
 * 
 * @param list 要初始化的线性表
 * @return 操作结果([0->失败]或[1->成功])
 */
Bool init(SQList *list)
{
    if (list->data)
    {
        free(list->data);
    }
    list->data = (Elemtype *)malloc(LIST_INIT_SIZE * sizeof(Elemtype));
    if (!list->data)
    {
        printf("内存分配失败!\n");
        return FALSE;
    }
    list->length = 0;
    list->listSize = LIST_INIT_SIZE;
    return TRUE;
}

/**
 * 新建并初始化一个空线性表 
 * 
 * @return 初始化后的线性表或NULL(当初始化失败时)
 */
SQList *init()
{
    SQList *list = (SQList *)calloc(1, sizeof(SQList));
    if (!list)
    {
        printf("内存分配失败!\n");
        return NULL;
    }
    if (init(list))
    {
        return list;
    }
    return NULL;
}

/**
 * 返回线性表目前长度
 */
int getLength(SQList *list)
{
    return list->length;
}

/**
 * 在线性表中定位给定的数据,并在找不到时返回0
 * 
 * @param list 线性表
 * @param elem 要定位的数据 
 * @return 数据在线性表中的位序或0
 */
int locate(SQList *list, Elemtype elem)
{
    Elemtype *data = list->data;
    for (int i = 0; i < list->length; i++)
    {
        if (data[i] == elem)
        {
            return i + 1; // 返回数组索引+1([1,length])
        }
    }
    return 0;
}

/**
 * 获取线性表中指定位置的元素 
 * 在索引越界时给出错误提示并结束程序
 * 
 * @param list 线性表
 * @param index 位序
 * @return 查找到的元素
 */
Elemtype getElem(SQList *list, int index)
{
    if (index < 1 || index > list->length)
    {
        printf("位序越界:%d 不在[1,%d]的范围内!\n", index, list->length);
        exit(-1);
    }
    return list->data[index - 1];
}

/**
 * 在线性表中指定位置插入新元素
 * 
 * @param list 线性表
 * @param index 位序
 * @param elem 新元素
 * @return 操作结果([0->失败]或[1->成功])
 */
Bool insert(SQList *list, int index, Elemtype elem)
{
    if (index < 1 || index > list->length + 1)
    {
        printf("插入位置错误:%d 不在[1,%d]的范围内!\n", index, list->length + 1);
        return FALSE;
    }
    // 当线性表长度≥容量时,给其扩容
    if (list->length >= list->listSize)
    {
        Elemtype *newData = (Elemtype *)realloc(list->data, sizeof(Elemtype) * (list->listSize + LIST_INCREMENT));
        if (!newData)
        {
            printf("重新分配空间错误!\n");
            return FALSE;
        }
        list->data = newData;
        list->listSize += LIST_INCREMENT;
    }
    // 移动元素
    for (int i = list->length; i >= index; i--)
    {
        list->data[i] = list->data[i - 1];
    }
    // 插入新元素
    list->data[index - 1] = elem;
    list->length += 1;
    return TRUE;
}

/**
 * 删除线性表中指定位置的元素并返回它
 * 
 * @param list 线性表
 * @param index 位序
 * @param elem 给一个指针用以返回删除的元素
 * @return 操作结果([0->失败]或[1->成功])
 */
Bool deleteElem(SQList *list, int index, Elemtype *elem)
{
    if (index < 1 || index > list->length)
    {
        printf("删除位置错误:%d 不在[1,%d]的范围内!\n", index, list->length);
        return FALSE;
    }
    // 当指针有效时才赋值
    if (elem)
    {
        *elem = list->data[index - 1];
    }
    // 删除(移动)元素
    for (int i = index - 1; i < list->length - 1; i++)
    {
        list->data[i] = list->data[i + 1];
    }
    list->length -= 1;
    return TRUE;
}

/**
 * 按序打印出线性表
 */
void display(SQList *list)
{
    printf("SQList[@%x]:\n", list);
    if (list->length == 0)
    {
        printf("[-空表-]\n");
        return;
    }
    for (int i = 0; i < list->length; i++)
    {
        if (i > 0)
        {
            printf("-> ");
        }
        printf("%d ", list->data[i]);
    }
    printf("\n");
}

// Test
int main(int argc, char const *argv[])
{
    SQList *list = init();
    int data[] = {5, 12, 45, 32, 1111, 33, 23, 455, 9, 0};
    for (int i = 0; i < 10; i++)
    {
        insert(list, i + 1, data[i]);
    }
    display(list); // 5 -> 12 -> 45 -> 32 -> 1111 -> 33 -> 23 -> 455 -> 9 -> 0
    return 0;
}

DataStruct/SQList.java

package DataStruct;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * 数据结构:
 * <p>
 * 线性表顺序存储结构定义和其基本方法
 * </p>
 * 
 * @author TagBug
 * @date 2021.09.18 21:08:48
 */
public class SQList<T> {
    private static final int LIST_INIT_SIZE = 100;
    private static final int LIST_INCREMENT = 10;

    private T[] data;
    private int length;
    private int listSize;

    /**
     * 线性表初始化
     * 
     * @param type 元素类型
     */
    @SuppressWarnings("unchecked")
    public SQList(Class<T> type) {
        data = (T[]) Array.newInstance(type, LIST_INIT_SIZE);
        length = 0;
        listSize = LIST_INIT_SIZE;
    }

    /**
     * 使用给定数据创建新线性表
     * 
     * @param type 元素类型
     * @param arr  数据数组
     */
    public SQList(Class<T> type, T[] arr) {
        this(type);
        for (int i = 0; i < arr.length; i++) {
            insert(i + 1, arr[i]);
        }
    }

    /**
     * 在线性表中定位给定的数据,并在找不到时返回0
     * 
     * @param elem 要定位的数据
     * @return 数据在线性表中的位序或0
     */
    public int locate(T elem) {
        for (int i = 0; i < length; i++) {
            if (data[i] == elem) {
                return i + 1; // 返回数组索引+1([1,length])
            }
        }
        return 0;
    }

    /**
     * 获取线性表中指定位置的元素
     * 
     * @param index 位序
     * @return 查找到的元素
     * @throws IndexOutOfBoundsException 当位序越界时抛出
     */
    public T getElem(int index) throws IndexOutOfBoundsException {
        if (index < 1 || index > length) {
            throw new IndexOutOfBoundsException(String.format("位序越界:%d 不在[1,%d]的范围内!\n", index, length));
        }
        return data[index - 1];
    }

    /**
     * 在线性表中指定位置插入新元素
     * 
     * @param index 位序
     * @param elem  新元素
     * @throws IndexOutOfBoundsException 当位序越界时抛出
     */
    public void insert(int index, T elem) throws IndexOutOfBoundsException {
        if (index < 1 || index > length + 1) {
            throw new IndexOutOfBoundsException(String.format("位序越界:%d 不在[1,%d]的范围内!\n", index, length));
        }
        // 当线性表长度≥容量时,给其扩容
        if (length >= listSize) {
            listSize += LIST_INCREMENT;
            data = Arrays.copyOf(data, listSize);
        }
        // 移动元素
        for (int i = length; i >= index; i--) {
            data[i] = data[i - 1];
        }
        // 插入新元素
        data[index - 1] = elem;
        length += 1;
    }

    /**
     * 删除线性表中指定位置的元素并返回它
     * 
     * @param index 位序
     * @return 删除的元素
     * @throws IndexOutOfBoundsException 当位序越界时抛出
     */
    public T delete(int index) throws IndexOutOfBoundsException {
        if (index < 1 || index > length) {
            throw new IndexOutOfBoundsException(String.format("位序越界:%d 不在[1,%d]的范围内!\n", index, length));
        }
        T deletedElem = data[index - 1];
        // 删除(移动)元素
        for (int i = index - 1; i < length - 1; i++) {
            data[i] = data[i + 1];
        }
        length -= 1;
        return deletedElem;
    }

    /**
     * 返回线性表目前长度
     */
    public int getLength() {
        return length;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(super.toString());
        sb.append(":\n");
        if (length == 0) {
            sb.append("[-空表-]");
            return sb.toString();
        }
        for (int i = 0; i < length; i++) {
            if (i > 0) {
                sb.append("-> ");
            }
            sb.append(data[i]);
            sb.append(' ');
        }
        return sb.toString();
    }

    /**
     * 单元测试
     */
    public static void main(String[] args) {
        Integer[] data = { 5, 12, 45, 32, 1111, 33, 23, 455, 9, 0 };
        SQList<Integer> list = new SQList<>(Integer.class, data);
        System.out.println(list); // 5 -> 12 -> 45 -> 32 -> 1111 -> 33 -> 23 -> 455 -> 9 -> 0
        list.delete(4);
        list.delete(6);
        System.out.println(list); // 5 -> 12 -> 45 -> 1111 -> 33 -> 455 -> 9 -> 0
        System.out.println(list.locate(9)); // 7
        System.out.println(list.getLength()); // 8
        list.insert(3, 101);
        System.out.println(list); // 5 -> 12 -> 101 -> 45 -> 1111 -> 33 -> 455 -> 9 -> 0
    }
}

链表(链式存储结构)

LinkList.c

/**
 * 数据结构:
 * 线性表链式存储结构定义和其基本方法
 * 
 * @author TagBug
 * @date 2021.09.16 16:51:05
 */
#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0

typedef unsigned short Bool;
typedef int Elemtype;
/**
 * Node默认为数据节点,保存数据信息和下一元素指针
 * LinkList默认为头结点,缓存链表长度信息
 */
typedef struct Node
{
    Elemtype data;
    Node *next;
} Node;
typedef struct
{
    int length;
    Node *next;
} LinkList;

/**
 * 获取链表中指定位序数据
 * 
 * @param head 链表头
 * @param index 位序
 * @param elem 用于存放查找到的数据元素
 * @return 查找结果
 */
Bool getElem(LinkList *head, int index, Elemtype *elem)
{
    if (index < 1 || index > head->length)
    {
        printf("位序越界:%d 不在[1,%d]的范围内!\n", index, head->length);
        return FALSE;
    }
    Node *node = head->next;
    for (int i = 1; i < index; i++)
    {
        /* if (!node->next)
        {
            printf("链表内部出错!链表长度与实际不符:(%d < %d)\n", i, head->length);
            return FALSE;
        } */
        node = node->next;
    }
    // 当指针有效时才赋值
    if (elem)
    {
        *elem = node->data;
    }
    return TRUE;
}

/**
 * 获取链表目前长度
 */
int getLength(LinkList *head)
{
    return head->length;
}

/**
 * 在链表中定位给定的数据,并在找不到时返回0
 * 
 * @param head 链表头
 * @param elem 要查找的元素
 * @return 元素位序或0
 */
int locateElem(LinkList *head, Elemtype elem)
{
    Node *node = head->next;
    int index = 1;
    while (node)
    {
        if (node->data == elem)
        {
            return index;
        }
        node = node->next;
        index++;
    }
    return 0;
}

/**
 * 向链表中插入新元素
 * 
 * @param head 链表头
 * @param index 位序
 * @param elem 要插入的新元素
 * @return 插入结果
 */
Bool insertElem(LinkList *head, int index, Elemtype elem)
{
    if (index < 1 || index > head->length + 1)
    {
        printf("位序越界:%d 不在[1,%d]的范围内!\n", index, head->length);
        return FALSE;
    }
    // 单独判断如果是插入第一个元素的情况
    if (index == 1)
    {
        Node *node = (Node *)calloc(1, sizeof(Node));
        if (!node)
        {
            printf("内存分配失败!\n");
            return FALSE;
        }
        node->data = elem;
        head->next = node;
        head->length += 1;
        return TRUE;
    }
    // index >= 2
    Node *node = head->next;
    for (int i = 2; i < index; i++)
    {
        /* if (!node->next)
        {
            printf("链表内部出错!链表长度与实际不符:(%d < %d)\n", i, head->length);
            return FALSE;
        } */
        node = node->next;
    }
    Node *newNode = (Node *)calloc(1, sizeof(Node));
    if (!newNode)
    {
        printf("内存分配失败!\n");
        return FALSE;
    }
    newNode->data = elem;
    newNode->next = node->next;
    node->next = newNode;
    head->length += 1;
    return TRUE;
}

/**
 * 从链表中删除指定位序的元素
 * 
 * @param head 链表头
 * @param index 位序
 * @param elem 用于保存删除掉的元素
 * @return 删除结果
 */
Bool deleteElem(LinkList *head, int index, Elemtype *elem)
{
    if (index < 1 || index > head->length)
    {
        printf("位序越界:%d 不在[1,%d]的范围内!\n", index, head->length);
        return FALSE;
    }
    // 单独判断如果是删除第一个元素的情况
    if (index == 1)
    {
        Node *node = head->next;
        // 当指针有效时才赋值
        if (elem)
        {
            *elem = node->data;
        }
        head->next = node->next;
        free(node);
        head->length -= 1;
        return TRUE;
    }
    // index >= 2
    Node *node = head->next;
    for (int i = 2; i < index; i++)
    {
        /* if (!node->next)
        {
            printf("链表内部出错!链表长度与实际不符:(%d < %d)\n", i, head->length);
            return FALSE;
        } */
        node = node->next;
    }
    Node *deletedNode = node->next;
    // 当指针有效时才赋值
    if (elem)
    {
        *elem = deletedNode->data;
    }
    node->next = deletedNode->next;
    free(deletedNode);
    head->length -= 1;
    return TRUE;
}

/**
 * 创建一个新的空链表
 * 
 * @return 链表头或NULL(内存分配失败时)
 */
LinkList *createLink()
{
    LinkList *head = (LinkList *)calloc(1, sizeof(LinkList));
    // length=0  next=NULL
    if (!head)
    {
        printf("内存分配失败!\n");
    }
    return head;
}

/**
 * 用给定数据创建一个新的线性表
 * 
 * @param arr 数组
 * @param length 数组长度
 * @return 链表头或NULL(内存分配失败时)
 */
LinkList *createLink(Elemtype *arr, int length)
{
    // 创建表头
    LinkList *head = createLink();
    if (!head)
    {
        return NULL;
    }
    // 创建数据节点
    for (int i = 1; i <= length; i++)
    {
        Bool result = insertElem(head, i, arr[i - 1]);
        // 如果创建失败则复原
        if (!result)
        {
            for (int j = i; j >= 1; j--)
            {
                deleteElem(head, j, NULL);
            }
            free(head);
            return NULL;
        }
    }
    return head;
}

/**
 * 按序打印出链表
 */
void display(LinkList *head)
{
    printf("LinkList[@%x]:\n", head);
    Node *node = head->next;
    if (!node)
    {
        printf("[-空表-]\n");
        return;
    }
    printf("%d ", node->data);
    node = node->next;
    while (node)
    {
        printf("-> ");
        printf("%d ", node->data);
        node = node->next;
    }
    printf("\n");
}

// Test
int main(int argc, char const *argv[])
{
    Elemtype arr[10] = {5, 12, 45, 32, 1111, 33, 23, 455, 9, 0};
    LinkList *list = createLink(arr, 10);
    display(list); // 5 -> 12 -> 45 -> 32 -> 1111 -> 33 -> 23 -> 455 -> 9 -> 0
    return 0;
}

DataStruct/LinkList.java

package DataStruct;

/**
 * 数据结构:
 * <p>
 * 线性表链式存储结构定义和其基本方法
 * </p>
 * 
 * @author TagBug
 * @date 2021.09.18 21:09:09
 */
public class LinkList<T> {
    private class Node {
        T data;
        Node next;
    }

    private int length;
    private Node head;

    /**
     * 创建一个新的空链表
     */
    public LinkList() {
        length = 0;
        head = null;
    }

    /**
     * 用给定数据创建一个新的链表
     * 
     * @param arr 数据数组
     */
    public LinkList(T[] arr) {
        this();
        // 创建数据节点
        for (int i = 1; i <= arr.length; i++) {
            insert(i, arr[i - 1]);
        }
    }

    /**
     * 获取链表中指定位序数据
     * 
     * @param index 位序
     * @return 查找结果
     * @throws IndexOutOfBoundsException 当位序越界时抛出
     */
    public T getElem(int index) throws IndexOutOfBoundsException {
        if (index < 1 || index > length) {
            throw new IndexOutOfBoundsException(String.format("位序越界:%d 不在[1,%d]的范围内!\n", index, length));
        }
        Node node = head;
        for (int i = 1; i < index; i++) {
            if (node == null) {
                throw new NullPointerException(String.format("链表内部出错!链表长度与实际不符:(%d < %d)\n", i, length));
            }
            node = node.next;
        }
        return node.data;
    }

    /**
     * 在链表中定位给定的数据,并在找不到时返回0
     * 
     * @param elem 要查找的元素
     * @return 元素位序或0
     */
    public int locate(T elem) {
        Node node = head;
        int index = 1;
        while (node != null) {
            if (node.data == elem) {
                return index;
            }
            node = node.next;
            index++;
        }
        return 0;
    }

    /**
     * 向链表中插入新元素
     * 
     * @param index 位序
     * @param elem  要插入的新元素
     */
    public void insert(int index, T elem) {
        if (index < 1 || index > length + 1) {
            throw new IndexOutOfBoundsException(String.format("位序越界:%d 不在[1,%d]的范围内!\n", index, length));
        }
        // 单独判断如果是插入第一个元素的情况
        if (index == 1) {
            head = new Node();
            head.data = elem;
            length += 1;
            return;
        }
        // index >= 2
        Node node = head;
        for (int i = 2; i < index; i++) {
            if (node == null) {
                throw new NullPointerException(String.format("链表内部出错!链表长度与实际不符:(%d < %d)\n", i, length));
            }
            node = node.next;
        }
        Node newNode = new Node();
        newNode.data = elem;
        newNode.next = node.next;
        node.next = newNode;
        length += 1;
    }

    /**
     * 从链表中删除并返回指定位序的元素
     * 
     * @param head  链表头
     * @param index 位序
     */
    public T delete(int index) {
        if (index < 1 || index > length) {
            throw new IndexOutOfBoundsException(String.format("位序越界:%d 不在[1,%d]的范围内!\n", index, length));
        }
        // 单独判断如果是删除第一个元素的情况
        if (index == 1) {
            Node node = head.next;
            // 当指针有效时才赋值
            T deletedElem = node.data;
            head.next = node.next;
            length -= 1;
            return deletedElem;
        }
        // index >= 2
        Node node = head;
        for (int i = 2; i < index; i++) {
            if (node == null) {
                throw new NullPointerException(String.format("链表内部出错!链表长度与实际不符:(%d < %d)\n", i, length));
            }
            node = node.next;
        }
        Node deletedNode = node.next;
        T deletedElem = deletedNode.data;
        node.next = deletedNode.next;
        length -= 1;
        return deletedElem;
    }

    /**
     * 获取链表长度
     */
    public int getLength() {
        return length;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(super.toString());
        sb.append(":\n");
        Node node = head;
        if (node == null) {
            sb.append("[-空表-]");
            return sb.toString();
        }
        sb.append(node.data);
        sb.append(' ');
        node = node.next;
        while (node != null) {
            sb.append("-> ");
            sb.append(node.data);
            sb.append(' ');
            node = node.next;
        }
        return sb.toString();
    }

    /**
     * 单元测试
     */
    public static void main(String[] args) {
        Integer[] data = { 5, 12, 45, 32, 1111, 33, 23, 455, 9, 0 };
        LinkList<Integer> list = new LinkList<>(data);
        System.out.println(list); // 5 -> 12 -> 45 -> 32 -> 1111 -> 33 -> 23 -> 455 -> 9 -> 0
        list.delete(4);
        list.delete(6);
        System.out.println(list); // 5 -> 12 -> 45 -> 1111 -> 33 -> 455 -> 9 -> 0
        System.out.println(list.locate(9)); // 7
        System.out.println(list.getLength()); // 8
        list.insert(3, 101);
        System.out.println(list); // 5 -> 12 -> 101 -> 45 -> 1111 -> 33 -> 455 -> 9 -> 0
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值